"use client";

import { useState, useEffect, useRef } from "react";
import { createPortal } from "react-dom";
import { usePathname, useRouter } from "next/navigation";
import { motion, AnimatePresence } from "framer-motion";
import { useAuthStore, useAuthSession } from "@/features/auth/stores/auth.store";
import { accountService } from "@/features/account/api/account.api";
import { Bars3Icon } from "@heroicons/react/24/outline";
import { Sidebar } from "./Sidebar";
import { baseNavigation } from "./navigation";
import { Logo } from "@/components/atoms/logo";
import { NotificationBell } from "@/features/notifications";

interface AppShellProps {
  children: React.ReactNode;
}

const prefetchUrls: string[] = (() => {
  const hrefs = new Set<string>();
  for (const item of baseNavigation) {
    if (item.href && item.href !== "#") hrefs.add(item.href);
    if (!item.children || item.children.length === 0) continue;
    for (const child of item.children.slice(0, 5)) {
      if (child.href && child.href !== "#") hrefs.add(child.href);
    }
  }
  return [...hrefs];
})();

// Sidebar and navigation are modularized in ./Sidebar and ./navigation

function useAppShellAuth(pathname: string) {
  const { user, isAuthenticated } = useAuthSession();
  const checkAuth = useAuthStore(state => state.checkAuth);
  const hasCheckedAuth = useAuthStore(state => state.hasCheckedAuth);
  const loading = useAuthStore(state => state.loading);
  const hydrateUserProfile = useAuthStore(state => state.hydrateUserProfile);
  const router = useRouter();
  const authCheckInitiated = useRef(false);

  useEffect(() => {
    if (!hasCheckedAuth && !authCheckInitiated.current) {
      authCheckInitiated.current = true;
      void checkAuth();
    }
  }, [hasCheckedAuth, checkAuth]);

  useEffect(() => {
    if (hasCheckedAuth && !isAuthenticated && !loading) {
      const destination = pathname || "/account";
      router.push(`/auth/login?redirect=${encodeURIComponent(destination)}`);
    }
  }, [hasCheckedAuth, isAuthenticated, loading, pathname, router]);

  useEffect(() => {
    if (!hasCheckedAuth || !isAuthenticated) return;
    if (user?.firstname && user?.lastname) return;
    void (async () => {
      try {
        const prof = await accountService.getProfile();
        if (!prof) return;
        hydrateUserProfile({
          firstname: prof.firstname ?? undefined,
          lastname: prof.lastname ?? undefined,
          phonenumber: prof.phonenumber ?? undefined,
        });
      } catch {
        // best-effort profile hydration
      }
    })();
  }, [hasCheckedAuth, hydrateUserProfile, isAuthenticated, user?.firstname, user?.lastname]);

  return {
    user,
    isAuthenticated,
    hasCheckedAuth,
    loading,
    isAuthReady: hasCheckedAuth && isAuthenticated,
    isCheckingAuth: !hasCheckedAuth || loading,
  };
}

function useSidebarExpansion(pathname: string) {
  const [expandedItems, setExpandedItems] = useState<string[]>([]);

  useEffect(() => {
    if (typeof window !== "undefined") {
      localStorage.setItem("sidebar-expanded-items", JSON.stringify(expandedItems));
    }
  }, [expandedItems]);

  useEffect(() => {
    try {
      const saved = localStorage.getItem("sidebar-expanded-items");
      if (!saved) return;
      const parsed = JSON.parse(saved) as unknown;
      if (Array.isArray(parsed) && parsed.every(x => typeof x === "string")) {
        setExpandedItems(prev => {
          const next = parsed;
          if (next.length === prev.length && next.every(v => prev.includes(v))) return prev;
          return next;
        });
      }
    } catch {
      // ignore
    }
  }, []);

  useEffect(() => {
    setExpandedItems(prev => {
      const next = new Set(prev);
      if (pathname.startsWith("/account/subscriptions")) next.add("Subscriptions");
      const result = [...next];
      if (result.length === prev.length && result.every(v => prev.includes(v))) return prev;
      return result;
    });
  }, [pathname]);

  const toggleExpanded = (itemName: string) => {
    setExpandedItems(prev =>
      prev.includes(itemName) ? prev.filter(name => name !== itemName) : [...prev, itemName]
    );
  };

  return { expandedItems, toggleExpanded };
}

/**
 * Portals the NotificationBell into the PageLayout header slot (#page-header-end).
 * Lives in AppShell so it never remounts on page navigation, preserving polling timers.
 * Re-targets when the DOM element changes (page navigation causes PageLayout remount).
 */
function PortaledNotificationBell() {
  const [target, setTarget] = useState<HTMLElement | null>(null);

  useEffect(() => {
    const sync = () => {
      const el = document.getElementById("page-header-end");
      setTarget(prev => (prev === el ? prev : el));
    };
    sync();
    const observer = new MutationObserver(sync);
    observer.observe(document.body, { childList: true, subtree: true });
    return () => observer.disconnect();
  }, []);

  if (!target) return null;
  return createPortal(<NotificationBell />, target);
}

function AuthLoadingSkeleton() {
  return (
    <div className="p-6 md:p-8 lg:p-10">
      <div className="space-y-6 animate-pulse">
        <div className="space-y-3">
          <div className="h-4 bg-muted rounded w-24" />
          <div className="h-8 bg-muted rounded w-48" />
        </div>
        <div className="h-32 bg-muted rounded-xl" />
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
          <div className="h-40 bg-muted rounded-xl" />
          <div className="h-40 bg-muted rounded-xl" />
        </div>
      </div>
    </div>
  );
}

export function AppShell({ children }: AppShellProps) {
  const [sidebarOpen, setSidebarOpen] = useState(false);
  const pathname = usePathname();
  const router = useRouter();
  const { user, isAuthReady, isCheckingAuth } = useAppShellAuth(pathname);
  const { expandedItems, toggleExpanded } = useSidebarExpansion(pathname);
  const navigation = baseNavigation;

  useEffect(() => {
    for (const href of prefetchUrls) {
      try {
        router.prefetch(href);
      } catch {
        /* best-effort */
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps -- prefetchUrls is static; router is unstable but functionally stable
  }, []);

  return (
    <>
      <div className="h-screen flex overflow-hidden bg-background">
        {/* Mobile sidebar overlay */}
        <AnimatePresence>
          {sidebarOpen && (
            <div className="fixed inset-0 flex z-50 md:hidden">
              <motion.div
                className="fixed inset-0 bg-black/50"
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                exit={{ opacity: 0 }}
                transition={{ duration: 0.3 }}
                onClick={() => setSidebarOpen(false)}
              />
              <motion.div
                className="relative flex-1 flex flex-col max-w-xs w-full bg-sidebar border-r border-sidebar-border shadow-2xl"
                initial={{ x: "-100%" }}
                animate={{ x: 0 }}
                exit={{ x: "-100%" }}
                transition={{ duration: 0.3, ease: "easeOut" }}
              >
                <div className="absolute top-0 right-0 -mr-12 pt-2" />
                <Sidebar
                  navigation={navigation}
                  pathname={pathname}
                  expandedItems={expandedItems}
                  toggleExpanded={toggleExpanded}
                  isMobile
                  user={
                    user
                      ? {
                          firstName: user.firstname ?? null,
                          lastName: user.lastname ?? null,
                          email: user.email,
                        }
                      : null
                  }
                  profileReady={!!(user?.firstname || user?.lastname)}
                />
              </motion.div>
            </div>
          )}
        </AnimatePresence>

        {/* Desktop sidebar */}
        <div className="hidden md:flex md:flex-shrink-0">
          <div className="flex flex-col w-[220px] border-r border-sidebar-border/40 bg-sidebar">
            <Sidebar
              navigation={navigation}
              pathname={pathname}
              expandedItems={expandedItems}
              toggleExpanded={toggleExpanded}
              user={
                user
                  ? {
                      firstName: user.firstname ?? null,
                      lastName: user.lastname ?? null,
                      email: user.email,
                    }
                  : null
              }
              profileReady={!!(user?.firstname || user?.lastname)}
            />
          </div>
        </div>

        {/* Main content */}
        <div className="flex flex-col w-0 flex-1 overflow-hidden bg-background">
          {/* Mobile-only hamburger bar */}
          <div className="md:hidden flex items-center h-16 px-3 border-b border-border/40 bg-background">
            <button
              type="button"
              className="flex items-center justify-center w-10 h-10 -ml-1 rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted/60 active:bg-muted transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-primary/20"
              onClick={() => setSidebarOpen(true)}
              aria-label="Open navigation"
            >
              <Bars3Icon className="h-5 w-5" />
            </button>
            <div className="ml-2">
              <Logo size={20} />
            </div>
          </div>

          {/* Main content area */}
          <main className="flex-1 relative overflow-y-auto focus:outline-none">
            {isCheckingAuth && <AuthLoadingSkeleton />}
            {!isCheckingAuth && isAuthReady && children}
          </main>
        </div>
      </div>

      {/* Persistent notification bell — portaled into PageLayout header */}
      {isAuthReady && <PortaledNotificationBell />}
    </>
  );
}
