"use client";

import { useCallback, useEffect, useState, type ReactNode } from "react";
import { useRouter } from "next/navigation";
import { useAuth } from "@/components/auth/AuthProvider";
import { ErrorState } from "@/components/ui/ErrorState";
import type { AccountType, User } from "@/types/auth";
import { DashboardHeader } from "./DashboardHeader";
import { DashboardMobileNav } from "./DashboardMobileNav";
import { DashboardSidebar } from "./DashboardSidebar";

function DashboardChrome({ children }: { children: ReactNode }) {
  return (
    <div className="fixed inset-0 flex overflow-hidden bg-bg">
      <aside className="hidden h-full min-h-0 w-sidebar shrink-0 border-r border-line bg-surface lg:flex lg:flex-col" aria-hidden="true">
        <div className="flex h-dashboard-header shrink-0 items-center border-b border-line px-4">
          <div className="h-6 w-32 rounded-pv bg-line" />
        </div>
        <div className="flex flex-1 flex-col gap-2 px-4 py-5">
          <div className="h-10 rounded-pv bg-line/80" />
          <div className="h-10 rounded-pv bg-line/60" />
          <div className="h-10 rounded-pv bg-line/60" />
        </div>
      </aside>
      <div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
        <div className="h-dashboard-header shrink-0 border-b border-line" />
        <div className="flex min-h-0 flex-1 items-center justify-center overflow-y-auto px-4 py-10">{children}</div>
      </div>
    </div>
  );
}

export function DashboardShell({
  title,
  allowedAccountTypes,
  children,
}: {
  title: string | ((user: User) => string);
  /** When set, other account types are redirected to `/dashboard`. */
  allowedAccountTypes?: readonly AccountType[];
  children: (user: User) => ReactNode;
}) {
  const router = useRouter();
  const { user, isLoading, isSessionVerified, logout, refresh } = useAuth();
  const [loadError, setLoadError] = useState(false);
  const [navOpen, setNavOpen] = useState(false);
  const [isLoggingOut, setIsLoggingOut] = useState(false);
  const [isRetrying, setIsRetrying] = useState(false);

  const closeNav = useCallback(() => setNavOpen(false), []);

  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) {
      return;
    }

    if (!isSessionVerified) {
      setLoadError(true);
      return;
    }

    setLoadError(false);

    if (!user) {
      router.replace("/signin");
      return;
    }

    if (!user.email_verified) {
      router.replace("/verify-email");
      return;
    }

    if (user.account_type === "brand" && !user.onboarding_completed) {
      router.replace("/signup/brand-setup");
      return;
    }

    if (allowedAccountTypes && !allowedAccountTypes.includes(user.account_type)) {
      router.replace("/dashboard");
    }
  }, [isLoading, isSessionVerified, user, router, allowedAccountTypes]);

  async function handleLogout() {
    if (isLoggingOut) {
      return;
    }

    setIsLoggingOut(true);

    try {
      await logout();
    } finally {
      router.replace("/signin");
    }
  }

  async function handleRetry() {
    if (isRetrying) {
      return;
    }

    setIsRetrying(true);

    try {
      await refresh();
      setLoadError(false);
    } catch {
      setLoadError(true);
    } finally {
      setIsRetrying(false);
    }
  }

  if (loadError) {
    return (
      <DashboardChrome>
        <div className="w-full max-w-md">
          <ErrorState
            title="Unable to load your account"
            message="We couldn't verify your session. This is a connection problem, not a sign-out."
            onRetry={() => {
              void handleRetry();
            }}
            isRetrying={isRetrying}
            retryLabel={isRetrying ? "Trying…" : "Try again"}
          />
        </div>
      </DashboardChrome>
    );
  }

  if (
    !isSessionVerified ||
    isLoading ||
    !user ||
    !user.email_verified ||
    (allowedAccountTypes && !allowedAccountTypes.includes(user.account_type))
  ) {
    return (
      <DashboardChrome>
        <p className="text-[0.95rem] font-medium text-ink-60" role="status" aria-live="polite">
          {isSessionVerified && !user
            ? "Redirecting to sign in…"
            : isSessionVerified && user && !user.email_verified
              ? "Redirecting to verify email…"
              : isSessionVerified &&
                  user &&
                  allowedAccountTypes &&
                  !allowedAccountTypes.includes(user.account_type)
                ? "Redirecting…"
                : "Loading dashboard…"}
        </p>
      </DashboardChrome>
    );
  }

  return (
    <div className="fixed inset-0 flex overflow-hidden bg-bg">
      <aside className="hidden h-full min-h-0 w-sidebar shrink-0 border-r border-line bg-surface lg:flex lg:flex-col">
        <DashboardSidebar
          accountType={user.account_type}
          onLogout={() => {
            void handleLogout();
          }}
          isLoggingOut={isLoggingOut}
        />
      </aside>

      <DashboardMobileNav
        open={navOpen}
        accountType={user.account_type}
        onLogout={() => {
          void handleLogout();
        }}
        isLoggingOut={isLoggingOut}
        onClose={closeNav}
      />

      <div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
        <DashboardHeader
          title={typeof title === "function" ? title(user) : title}
          user={user}
          onOpenNav={() => setNavOpen(true)}
          navOpen={navOpen}
        />
        <main id="main-content" className="min-h-0 min-w-0 flex-1 overflow-x-hidden overflow-y-auto px-4 py-4 md:px-5 md:py-5">
          {children(user)}
        </main>
      </div>
    </div>
  );
}
