"use client";

import { useCallback, useEffect, useState, type ReactNode } from "react";
import { useRouter } from "next/navigation";
import { AdminHeader } from "@/components/admin/AdminHeader";
import { AdminSidebar } from "@/components/admin/AdminSidebar";
import { ErrorState } from "@/components/ui/ErrorState";
import { Skeleton } from "@/components/ui/Skeleton";
import { adminApi } from "@/lib/api/admin";
import { ApiError } from "@/lib/api";
import { cn } from "@/lib/cn";
import type { AdminUser } from "@/types/admin";

const ADMIN_CACHE_KEY = "pv.admin.user";

function readCachedAdmin(): AdminUser | null {
  if (typeof window === "undefined") {
    return null;
  }
  try {
    const raw = sessionStorage.getItem(ADMIN_CACHE_KEY);
    if (!raw) {
      return null;
    }
    const parsed = JSON.parse(raw) as AdminUser;
    if (
      typeof parsed?.id === "number" &&
      typeof parsed?.name === "string" &&
      typeof parsed?.email === "string"
    ) {
      return parsed;
    }
  } catch {
    // ignore cache parse errors
  }
  return null;
}

export function writeAdminCache(admin: AdminUser | null): void {
  if (typeof window === "undefined") {
    return;
  }
  if (!admin) {
    sessionStorage.removeItem(ADMIN_CACHE_KEY);
    return;
  }
  sessionStorage.setItem(ADMIN_CACHE_KEY, JSON.stringify(admin));
}

function AdminChromeSkeleton() {
  return (
    <div className="fixed inset-0 flex overflow-hidden bg-[#F7F8FA]" aria-busy="true" aria-live="polite">
      <aside className="hidden h-full w-sidebar shrink-0 border-r border-line/80 bg-surface lg:flex lg:flex-col">
        <div className="flex h-dashboard-header items-center border-b border-line/80 px-4">
          <Skeleton className="h-6 w-28" />
        </div>
        <div className="space-y-2 px-3 py-4">
          <Skeleton className="h-3 w-16" />
          <Skeleton className="h-9 w-full rounded-[10px]" />
          <Skeleton className="mt-4 h-3 w-14" />
          <Skeleton className="h-9 w-full rounded-[10px]" />
          <Skeleton className="h-9 w-full rounded-[10px]" />
        </div>
      </aside>
      <div className="flex min-h-0 min-w-0 flex-1 flex-col">
        <div className="flex h-dashboard-header items-center border-b border-line/80 px-4 lg:px-6">
          <Skeleton className="h-5 w-32" />
        </div>
        <div className="flex flex-1 items-center justify-center">
          <p className="text-sm text-ink-40">Loading…</p>
        </div>
      </div>
    </div>
  );
}

export function AdminShell({
  title,
  subtitle,
  contentWidth = "full",
  children,
}: {
  title: string;
  subtitle?: string;
  /**
   * `full` uses the content column beside the sidebar (default — matches dashboard).
   * `contained` optionally keeps a page at `max-w-dashboard`.
   */
  contentWidth?: "contained" | "full";
  children: (admin: AdminUser) => ReactNode;
}) {
  const router = useRouter();
  // Start null on server and client to avoid sessionStorage hydration mismatches.
  const [admin, setAdmin] = useState<AdminUser | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [sessionVerified, setSessionVerified] = useState(false);
  const [loadError, setLoadError] = useState(false);
  const [navOpen, setNavOpen] = useState(false);
  const [isLoggingOut, setIsLoggingOut] = useState(false);

  const verify = useCallback(async () => {
    setIsLoading(true);
    setLoadError(false);
    try {
      const me = await adminApi.me();
      setAdmin(me);
      writeAdminCache(me);
      setSessionVerified(true);
    } catch (error) {
      if (error instanceof ApiError && error.kind === "unauthenticated") {
        setAdmin(null);
        writeAdminCache(null);
        setSessionVerified(true);
      } else {
        setLoadError(true);
        setSessionVerified(false);
      }
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    const cached = readCachedAdmin();
    if (cached) {
      setAdmin(cached);
    }
    void verify();
  }, [verify]);

  useEffect(() => {
    const html = document.documentElement;
    const { body } = document;
    const previousHtmlOverflow = html.style.overflow;
    const previousBodyOverflow = body.style.overflow;
    html.style.overflow = "hidden";
    body.style.overflow = "hidden";
    return () => {
      html.style.overflow = previousHtmlOverflow;
      body.style.overflow = previousBodyOverflow;
    };
  }, []);

  useEffect(() => {
    if (isLoading || !sessionVerified) {
      return;
    }
    if (!admin) {
      router.replace("/admin/signin");
    }
  }, [admin, isLoading, sessionVerified, router]);

  async function handleLogout() {
    if (isLoggingOut) {
      return;
    }
    setIsLoggingOut(true);
    try {
      await adminApi.logout();
    } catch {
      // still clear local session
    } finally {
      writeAdminCache(null);
      setAdmin(null);
      setIsLoggingOut(false);
      router.replace("/admin/signin");
    }
  }

  if (loadError) {
    return (
      <div className="fixed inset-0 flex items-center justify-center bg-[#F7F8FA] px-4">
        <ErrorState
          title="Unable to verify admin session"
          message="Check your connection and try again."
          onRetry={() => void verify()}
        />
      </div>
    );
  }

  if (isLoading || !sessionVerified || !admin) {
    return <AdminChromeSkeleton />;
  }

  return (
    <div className="fixed inset-0 flex overflow-hidden bg-[#F7F8FA]">
      <aside className="hidden h-full min-h-0 w-sidebar shrink-0 border-r border-line/80 bg-surface lg:flex lg:flex-col">
        <AdminSidebar />
      </aside>

      {navOpen ? (
        <div className="fixed inset-0 z-40 lg:hidden">
          <button
            type="button"
            className="absolute inset-0 bg-primary/30"
            aria-label="Close navigation"
            onClick={() => setNavOpen(false)}
          />
          <aside className="absolute inset-y-0 left-0 w-sidebar border-r border-line/80 bg-surface shadow-pv">
            <AdminSidebar onNavigate={() => setNavOpen(false)} onClose={() => setNavOpen(false)} />
          </aside>
        </div>
      ) : null}

      <div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
        <AdminHeader
          title={title}
          subtitle={subtitle}
          adminName={admin.name}
          onLogout={() => void handleLogout()}
          isLoggingOut={isLoggingOut}
          onOpenNav={() => setNavOpen(true)}
        />
        <main id="main-content" className="min-h-0 flex-1 overflow-y-auto">
          <div
            className={cn(
              "w-full space-y-5 px-4 py-5 md:px-5 lg:px-6",
              contentWidth === "contained" && "mx-auto max-w-dashboard",
              contentWidth === "full" && "max-w-none",
            )}
          >
            {children(admin)}
          </div>
        </main>
      </div>
    </div>
  );
}
