import { useQuery } from "@tanstack/react-query";
import {
  ChevronDown,
  ClipboardCheck,
  KeyRound,
  LayoutDashboard,
  LogOut,
  Moon,
  NotebookTabs,
  ShieldHalf,
  Sun,
  User as UserIcon,
} from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { useAuth } from "react-oidc-context";
import { NavLink, Outlet, useLocation, useNavigate } from "react-router-dom";
import {
  AppSidebar,
  applyShellTheme,
  buildShellProfileSummary,
  buildShellSessionStatus,
  readShellSessionExpiryEnabled,
  readShellSidebarCollapsed,
  readShellTheme,
  type ShellSidebarNavItem,
  type ShellTranslator,
  shellLayoutClasses,
  writeShellSessionExpiryEnabled,
  writeShellSidebarCollapsed,
} from "../../../../common/shell";
import { fetchMe } from "../../features/auth/authApi";
import { t } from "../../lib/i18n";
import { resolveProfileRole } from "../../lib/role";
import {
  shouldAttemptSlidingSessionRenew,
  shouldAttemptUnlimitedSessionRenew,
} from "../../lib/sessionSliding";
import LanguageSelector from "../common/LanguageSelector";
import { Toaster } from "../ui/toaster";

const LOCALE_CHANGED_EVENT = "baron_locale_changed";

const baseNavItems: ShellSidebarNavItem[] = [
  {
    labelKey: "ui.dev.nav.overview",
    labelFallback: "Overview",
    to: "/",
    icon: LayoutDashboard,
    end: true,
  },
  {
    labelKey: "ui.dev.nav.clients",
    labelFallback: "Clients",
    to: "/clients",
    icon: ShieldHalf,
  },
  {
    labelKey: "ui.dev.nav.audit_logs",
    labelFallback: "Audit Logs",
    to: "/audit-logs",
    icon: NotebookTabs,
  },
  {
    labelKey: "ui.dev.nav.developer_request",
    labelFallback: "Developer Access Request",
    to: "/developer-requests",
    icon: ClipboardCheck,
  },
];

type SessionStatusProps = {
  expiresAtSec?: number | null;
  t: ShellTranslator;
};

function useSessionStatus({ expiresAtSec, t }: SessionStatusProps) {
  const [nowMs, setNowMs] = useState(() => Date.now());

  useEffect(() => {
    const timer = window.setInterval(() => {
      setNowMs(Date.now());
    }, 1000);

    return () => {
      window.clearInterval(timer);
    };
  }, []);

  return buildShellSessionStatus({ expiresAtSec, nowMs, t });
}

function SessionStatusBadge(props: SessionStatusProps) {
  const sessionStatus = useSessionStatus(props);

  return (
    <span
      className={[
        shellLayoutClasses.sessionBadge,
        sessionStatus.toneClass,
      ].join(" ")}
    >
      {sessionStatus.text}
    </span>
  );
}

function SessionStatusText(props: SessionStatusProps) {
  const sessionStatus = useSessionStatus(props);

  return <>{sessionStatus.text}</>;
}

function AppLayout() {
  const auth = useAuth();
  const location = useLocation();
  const navigate = useNavigate();
  const profileMenuRef = useRef<HTMLDivElement>(null);
  const isRenewInFlightRef = useRef(false);
  const lastRenewAttemptAtRef = useRef(0);
  const lastVisitedRouteRef = useRef<string | null>(null);
  const isDevelopmentRuntime = import.meta.env.MODE === "development";
  const [theme, setTheme] = useState<"light" | "dark">(readShellTheme);
  const [isProfileMenuOpen, setIsProfileMenuOpen] = useState(false);
  const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(() =>
    readShellSidebarCollapsed(false),
  );
  const [, setDevelopmentRenderRevision] = useState(0);
  const [isSessionExpiryEnabled, setIsSessionExpiryEnabled] = useState(() =>
    readShellSessionExpiryEnabled(!isDevelopmentRuntime),
  );
  const hasAccessToken = Boolean(auth.user?.access_token);
  const { data: profile } = useQuery({
    queryKey: ["userMe"],
    queryFn: fetchMe,
    enabled: hasAccessToken,
  });

  const handleLogout = () => {
    if (
      window.confirm(
        t("msg.dev.logout_confirm", "Are you sure you want to log out?"),
      )
    ) {
      auth.removeUser();
      navigate("/login");
    }
  };

  useEffect(() => {
    applyShellTheme(theme);
  }, [theme]);

  useEffect(() => {
    if (!isDevelopmentRuntime) {
      return;
    }

    const rerenderDevelopmentShell = () => {
      setDevelopmentRenderRevision((value) => value + 1);
    };

    window.addEventListener(LOCALE_CHANGED_EVENT, rerenderDevelopmentShell);

    return () => {
      window.removeEventListener(
        LOCALE_CHANGED_EVENT,
        rerenderDevelopmentShell,
      );
    };
  }, []);

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        profileMenuRef.current &&
        !profileMenuRef.current.contains(event.target as Node)
      ) {
        setIsProfileMenuOpen(false);
      }
    };

    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, []);

  useEffect(() => {
    const maybeRenewSession = async () => {
      const now = Date.now();
      if (
        !shouldAttemptSlidingSessionRenew({
          expiresAtSec: auth.user?.expires_at,
          nowMs: now,
          isEnabled: isSessionExpiryEnabled,
          isAuthenticated: auth.isAuthenticated,
          isLoading: auth.isLoading,
          isRenewInFlight: isRenewInFlightRef.current,
          lastAttemptAtMs: lastRenewAttemptAtRef.current,
        })
      ) {
        return;
      }

      isRenewInFlightRef.current = true;
      lastRenewAttemptAtRef.current = now;

      try {
        await auth.signinSilent();
      } catch (error) {
        console.error("Silent session renewal failed.", error);
      } finally {
        isRenewInFlightRef.current = false;
      }
    };

    const handleUserAction = () => {
      void maybeRenewSession();
    };

    window.addEventListener("pointerdown", handleUserAction);
    window.addEventListener("keydown", handleUserAction);

    return () => {
      window.removeEventListener("pointerdown", handleUserAction);
      window.removeEventListener("keydown", handleUserAction);
    };
  }, [
    auth,
    auth.isAuthenticated,
    auth.isLoading,
    auth.user?.expires_at,
    isSessionExpiryEnabled,
  ]);

  useEffect(() => {
    if (isDevelopmentRuntime) {
      return;
    }

    const maybeKeepSessionAlive = async () => {
      const now = Date.now();
      if (
        !shouldAttemptUnlimitedSessionRenew({
          expiresAtSec: auth.user?.expires_at,
          nowMs: now,
          isEnabled: isSessionExpiryEnabled,
          isAuthenticated: auth.isAuthenticated,
          isLoading: auth.isLoading,
          isRenewInFlight: isRenewInFlightRef.current,
          lastAttemptAtMs: lastRenewAttemptAtRef.current,
        })
      ) {
        return;
      }

      isRenewInFlightRef.current = true;
      lastRenewAttemptAtRef.current = now;

      try {
        await auth.signinSilent();
      } catch (error) {
        console.error("Unlimited session keepalive renewal failed.", error);
      } finally {
        isRenewInFlightRef.current = false;
      }
    };

    const timer = window.setInterval(() => {
      void maybeKeepSessionAlive();
    }, 30_000);

    void maybeKeepSessionAlive();

    return () => {
      window.clearInterval(timer);
    };
  }, [
    auth,
    auth.isAuthenticated,
    auth.isLoading,
    auth.user?.expires_at,
    isSessionExpiryEnabled,
  ]);

  useEffect(() => {
    const routeKey = `${location.pathname}${location.search}${location.hash}`;
    if (lastVisitedRouteRef.current === null) {
      lastVisitedRouteRef.current = routeKey;
      return;
    }

    if (lastVisitedRouteRef.current === routeKey) {
      return;
    }

    lastVisitedRouteRef.current = routeKey;

    const now = Date.now();
    if (
      !shouldAttemptSlidingSessionRenew({
        expiresAtSec: auth.user?.expires_at,
        nowMs: now,
        isEnabled: isSessionExpiryEnabled,
        isAuthenticated: auth.isAuthenticated,
        isLoading: auth.isLoading,
        isRenewInFlight: isRenewInFlightRef.current,
        lastAttemptAtMs: lastRenewAttemptAtRef.current,
      })
    ) {
      return;
    }

    isRenewInFlightRef.current = true;
    lastRenewAttemptAtRef.current = now;

    void auth
      .signinSilent()
      .catch((error) => {
        console.error("Silent session renewal failed.", error);
      })
      .finally(() => {
        isRenewInFlightRef.current = false;
      });
  }, [
    auth,
    auth.isAuthenticated,
    auth.isLoading,
    auth.user?.expires_at,
    isSessionExpiryEnabled,
    location.hash,
    location.pathname,
    location.search,
  ]);

  const toggleTheme = () => {
    setTheme((prev) => (prev === "light" ? "dark" : "light"));
  };

  const profileSummary = buildShellProfileSummary({
    profileName:
      profile?.name ||
      auth.user?.profile?.name?.toString() ||
      auth.user?.profile?.preferred_username?.toString() ||
      auth.user?.profile?.nickname?.toString(),
    profileEmail: profile?.email || auth.user?.profile?.email?.toString(),
    fallbackName: t("ui.shell.profile.unknown_name", "Unknown User"),
    fallbackEmail: t("ui.shell.profile.unknown_email", "unknown@example.com"),
  });
  const currentRole = resolveProfileRole(
    auth.user?.profile as Record<string, unknown> | undefined,
  );
  const displayRoleKey = profile?.role || currentRole;
  const navItems =
    displayRoleKey === "super_admin"
      ? [
          ...baseNavItems,
          {
            labelKey: "ui.dev.nav.developer_grants",
            labelFallback: "Developer Access Grants",
            to: "/developer-grants",
            icon: KeyRound,
          },
        ]
      : baseNavItems;
  const handleSessionExpiryToggle = () => {
    setIsSessionExpiryEnabled((prev) => {
      const next = !prev;
      writeShellSessionExpiryEnabled(next);
      return next;
    });
  };
  const handleSidebarToggle = () => {
    setIsSidebarCollapsed((prev) => {
      const next = !prev;
      writeShellSidebarCollapsed(next);
      return next;
    });
  };
  const sidebarNavContent = (
    <div className={shellLayoutClasses.navList}>
      {navItems.map(({ labelKey, labelFallback, to, icon: Icon }) => {
        const label = t(labelKey, labelFallback);

        return (
          <NavLink
            key={to}
            to={to}
            end={to === "/"}
            className={({ isActive }) =>
              [
                shellLayoutClasses.navItemBase,
                isSidebarCollapsed
                  ? shellLayoutClasses.navItemBaseCollapsed
                  : "",
                isActive
                  ? shellLayoutClasses.navItemActive
                  : shellLayoutClasses.navItemIdle,
              ].join(" ")
            }
            title={label}
            aria-label={label}
          >
            <Icon size={18} />
            <span className={isSidebarCollapsed ? "sr-only" : ""}>{label}</span>
          </NavLink>
        );
      })}
    </div>
  );
  const sidebarFooterContent = (
    <div className="border-t border-border/50 px-3 pt-4">
      <button
        type="button"
        onClick={handleLogout}
        className={
          isSidebarCollapsed
            ? shellLayoutClasses.logoutButtonCollapsed
            : shellLayoutClasses.logoutButton
        }
        title={t("ui.shell.nav.logout", "Logout")}
      >
        <LogOut size={18} />
        <span className={isSidebarCollapsed ? "sr-only" : ""}>
          {t("ui.shell.nav.logout", "Logout")}
        </span>
      </button>
    </div>
  );

  return (
    <div
      className={
        isSidebarCollapsed
          ? shellLayoutClasses.rootCollapsed
          : shellLayoutClasses.root
      }
    >
      <AppSidebar
        brandLabel={t("ui.dev.brand", "Baron Sign In")}
        brandTitle={t("ui.dev.console_title", "Developer Console")}
        brandIcon={<ShieldHalf size={20} />}
        navContent={sidebarNavContent}
        footerContent={sidebarFooterContent}
        collapsed={isSidebarCollapsed}
        onToggleCollapsed={handleSidebarToggle}
        collapseLabel={t("ui.shell.sidebar.collapse", "사이드바 접기")}
        expandLabel={t("ui.shell.sidebar.expand", "사이드바 펼치기")}
      />

      <div className={shellLayoutClasses.content}>
        <header className={shellLayoutClasses.header}>
          <div className={shellLayoutClasses.headerInner}>
            <div className={shellLayoutClasses.headerTitleWrap}>
              <p className="text-xs uppercase tracking-[0.22em] text-muted-foreground">
                {t("ui.dev.header.plane", "Dev Plane")}
              </p>
              <span className="text-lg font-semibold">
                {t("ui.dev.header.subtitle", "Manage your applications")}
              </span>
            </div>
            <div className={shellLayoutClasses.headerActions}>
              <LanguageSelector />
              <button
                type="button"
                onClick={toggleTheme}
                className={shellLayoutClasses.actionButton}
                aria-label={t("ui.common.theme_toggle", "Toggle theme")}
              >
                {theme === "light" ? <Sun size={16} /> : <Moon size={16} />}
                {theme === "light"
                  ? t("ui.common.theme_light", "Light")
                  : t("ui.common.theme_dark", "Dark")}
              </button>
              {isSessionExpiryEnabled ? (
                <SessionStatusBadge
                  expiresAtSec={auth.user?.expires_at}
                  t={t}
                />
              ) : null}
              <div className="relative" ref={profileMenuRef}>
                <button
                  type="button"
                  onClick={() => setIsProfileMenuOpen((prev) => !prev)}
                  className="inline-flex items-center gap-3 rounded-full border border-border bg-card px-3 py-2 transition hover:bg-muted/20"
                  aria-haspopup="menu"
                  aria-expanded={isProfileMenuOpen}
                  aria-label={t(
                    "ui.shell.profile.menu_aria",
                    "Open account menu",
                  )}
                >
                  <div className={shellLayoutClasses.profileInitial}>
                    {profileSummary.initial}
                  </div>
                  <div className="hidden min-w-0 text-left md:block">
                    <p className="truncate text-xs font-medium text-foreground">
                      {profileSummary.name}
                    </p>
                    <p className="truncate text-[11px] text-muted-foreground">
                      {profileSummary.email}
                    </p>
                  </div>
                  <ChevronDown
                    size={14}
                    className={`transition-transform duration-200 ${isProfileMenuOpen ? "rotate-180" : ""}`}
                  />
                </button>
                {isProfileMenuOpen ? (
                  <div role="menu" className={shellLayoutClasses.profileMenu}>
                    <p className="text-xs uppercase tracking-[0.16em] text-muted-foreground">
                      {t("ui.shell.profile.menu_title", "Account")}
                    </p>
                    <div className={shellLayoutClasses.profileCard}>
                      <div>
                        <p className="truncate text-sm font-semibold text-foreground">
                          {profileSummary.name}
                        </p>
                        <p className="truncate text-xs text-muted-foreground">
                          {profileSummary.email}
                        </p>
                      </div>
                      <div className="flex items-center pt-1">
                        <span className="inline-flex items-center rounded-full bg-sky-500/10 px-2.5 py-1 text-[10px] font-semibold text-sky-700 dark:text-sky-300">
                          {t(
                            `ui.shell.role.${displayRoleKey}`,
                            displayRoleKey.toUpperCase(),
                          )}
                        </span>
                      </div>
                    </div>

                    <div className={shellLayoutClasses.settingsCard}>
                      <div className="flex items-center justify-between gap-3">
                        <div>
                          <p className="text-sm font-medium text-foreground">
                            {t(
                              "ui.shell.session.auto_extend",
                              "Session expiry",
                            )}
                          </p>
                          <p className="text-xs text-muted-foreground">
                            {isSessionExpiryEnabled ? (
                              <SessionStatusText
                                expiresAtSec={auth.user?.expires_at}
                                t={t}
                              />
                            ) : (
                              t(
                                "ui.shell.session.disabled",
                                "Session expiry disabled",
                              )
                            )}
                          </p>
                        </div>
                        <button
                          type="button"
                          role="switch"
                          aria-checked={isSessionExpiryEnabled}
                          onClick={handleSessionExpiryToggle}
                          className={[
                            "relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition",
                            isSessionExpiryEnabled ? "bg-primary" : "bg-muted",
                          ].join(" ")}
                        >
                          <span
                            className={[
                              "inline-block h-5 w-5 rounded-full bg-white transition",
                              isSessionExpiryEnabled
                                ? "translate-x-5"
                                : "translate-x-1",
                            ].join(" ")}
                          />
                        </button>
                      </div>
                    </div>

                    <button
                      type="button"
                      role="menuitem"
                      className="mt-2 flex w-full items-center gap-2 rounded-lg border border-border px-3 py-2 text-left text-sm text-foreground transition hover:bg-muted/20"
                      onClick={() => {
                        navigate("/profile");
                        setIsProfileMenuOpen(false);
                      }}
                    >
                      <UserIcon size={16} className="text-muted-foreground" />
                      <span>{t("ui.shell.nav.profile", "My Profile")}</span>
                    </button>
                    <button
                      type="button"
                      role="menuitem"
                      className="mt-2 flex w-full items-center gap-2 rounded-lg border border-border px-3 py-2 text-left text-sm text-muted-foreground transition hover:bg-destructive/10 hover:text-destructive"
                      onClick={handleLogout}
                    >
                      <LogOut size={16} />
                      <span>{t("ui.shell.nav.logout", "Logout")}</span>
                    </button>
                  </div>
                ) : null}
              </div>
            </div>
          </div>
        </header>
        <main className={shellLayoutClasses.main}>
          <Outlet />
        </main>
      </div>
      <Toaster />
    </div>
  );
}

export default AppLayout;
