import { ChevronDown, Menu, Search as SearchIcon, X } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { Link, Outlet, useLocation, useNavigate } from "react-router-dom";
import { ArkLogoMark } from "../components/ArkLogoMark";
import { useI18n, type Lang } from "../i18n";
import { LANG_OPTIONS } from "../i18nLanguages";

type PublicNavWhich =
  | "home"
  | "browseAll"
  | "categories"
  | "browseLatest"
  | "browseRecommended"
  | "browsePopular"
  | "about";

function navIsActive(
  pathname: string,
  search: string,
  hash: string,
  which: PublicNavWhich,
): boolean {
  const sp = new URLSearchParams(search);
  switch (which) {
    case "home":
      return pathname === "/";
    case "browseAll":
      return pathname === "/browse" && !sp.has("sort");
    case "categories":
      return pathname === "/" && hash === "#categories";
    case "browseLatest":
      return pathname === "/" && hash === "#latest";
    case "browseRecommended":
      return pathname === "/" && hash === "#official";
    case "browsePopular":
      return pathname === "/" && hash === "#popular";
    case "about":
      return pathname === "/about";
    default:
      return false;
  }
}

function navClassName(active: boolean) {
  return [
    "shrink-0 rounded-sm px-2 py-2 text-[13px] font-medium leading-none whitespace-nowrap no-underline outline-none transition-colors",
    "focus-visible:ring-2 focus-visible:ring-ark-gold/90 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg",
    active
      ? "text-ark-gold visited:text-ark-gold"
      : "text-[#d7d7dc] visited:text-[#d7d7dc] hover:text-ark-gold",
  ].join(" ");
}

type LanguageDropdownProps = {
  lang: Lang;
  setLang: (lang: Lang) => void;
  ariaLabel: string;
  className?: string;
};

function flagSrc(code: Lang): string {
  return `/assets/ark-library/flags/${code}.svg`;
}

function FlagIcon({
  code,
  className = "",
}: {
  code: Lang;
  className?: string;
}) {
  return (
    <img
      src={flagSrc(code)}
      alt=""
      aria-hidden
      draggable={false}
      decoding="async"
      className={`shrink-0 rounded-full object-cover ${className}`}
    />
  );
}

function LanguageDropdown({
  lang,
  setLang,
  ariaLabel,
  className = "",
}: LanguageDropdownProps) {
  const [open, setOpen] = useState(false);
  const rootRef = useRef<HTMLDivElement>(null);
  const selected = LANG_OPTIONS.find((option) => option.code === lang);

  useEffect(() => {
    if (!open) return;

    const closeOnOutside = (event: MouseEvent | TouchEvent) => {
      if (!rootRef.current?.contains(event.target as Node)) setOpen(false);
    };
    const closeOnEscape = (event: KeyboardEvent) => {
      if (event.key === "Escape") setOpen(false);
    };

    document.addEventListener("mousedown", closeOnOutside);
    document.addEventListener("touchstart", closeOnOutside);
    window.addEventListener("keydown", closeOnEscape);
    return () => {
      document.removeEventListener("mousedown", closeOnOutside);
      document.removeEventListener("touchstart", closeOnOutside);
      window.removeEventListener("keydown", closeOnEscape);
    };
  }, [open]);

  return (
    <div ref={rootRef} className={`relative ${className}`}>
      <button
        type="button"
        onClick={() => setOpen((value) => !value)}
        className="flex h-full w-full items-center gap-2 rounded-full border border-ark-line bg-[#1a1b20] px-3 py-2 text-sm text-neutral-200 shadow-inner outline-none transition hover:border-ark-gold/50 focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg"
        aria-label={ariaLabel}
        aria-haspopup="listbox"
        aria-expanded={open}
      >
        <FlagIcon code={lang} className="h-5 w-5" />
        <span className="min-w-0 flex-1 truncate text-left">
          {selected?.label ?? lang}
        </span>
        <ChevronDown
          size={16}
          className={`shrink-0 text-neutral-400 transition ${
            open ? "rotate-180 text-ark-gold" : ""
          }`}
          aria-hidden
        />
      </button>

      {open ? (
        <div
          className="absolute left-0 right-0 top-[calc(100%+0.5rem)] z-50 overflow-hidden rounded-2xl border border-white/10 bg-[#1c1c21]/95 p-1.5 shadow-2xl shadow-black/70 ring-1 ring-ark-line/80 backdrop-blur-xl"
          role="listbox"
          aria-label={ariaLabel}
        >
          {LANG_OPTIONS.map((option) => {
            const active = option.code === lang;
            return (
              <button
                key={option.code}
                type="button"
                role="option"
                aria-selected={active}
                onClick={() => {
                  setLang(option.code as Lang);
                  setOpen(false);
                }}
                className={`flex w-full items-center gap-2 rounded-xl px-3 py-2 text-left text-sm transition ${
                  active
                    ? "bg-ark-gold/10 text-ark-gold2"
                    : "text-neutral-200 hover:bg-white/10 hover:text-white"
                }`}
              >
                <FlagIcon code={option.code} className="h-5 w-5" />
                <span className="truncate font-medium">{option.label}</span>
              </button>
            );
          })}
        </div>
      ) : null}
    </div>
  );
}

type MobileLanguageButtonProps = {
  lang: Lang;
  setLang: (lang: Lang) => void;
  ariaLabel: string;
  onOpen?: () => void;
};

function MobileLanguageButton({
  lang,
  setLang,
  ariaLabel,
  onOpen,
}: MobileLanguageButtonProps) {
  const [open, setOpen] = useState(false);
  const rootRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!open) return;

    const closeOnOutside = (event: MouseEvent | TouchEvent) => {
      if (!rootRef.current?.contains(event.target as Node)) setOpen(false);
    };
    const closeOnEscape = (event: KeyboardEvent) => {
      if (event.key === "Escape") setOpen(false);
    };

    document.addEventListener("mousedown", closeOnOutside);
    document.addEventListener("touchstart", closeOnOutside);
    window.addEventListener("keydown", closeOnEscape);
    return () => {
      document.removeEventListener("mousedown", closeOnOutside);
      document.removeEventListener("touchstart", closeOnOutside);
      window.removeEventListener("keydown", closeOnEscape);
    };
  }, [open]);

  return (
    <div ref={rootRef} className="relative shrink-0">
      <button
        type="button"
        onClick={() => {
          onOpen?.();
          setOpen((value) => !value);
        }}
        className="flex h-10 w-10 items-center justify-center overflow-hidden rounded-full bg-[#191921] outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-[#08070c]"
        aria-label={ariaLabel}
        aria-haspopup="listbox"
        aria-expanded={open}
      >
        <FlagIcon code={lang} className="h-7 w-7" />
      </button>

      {open ? (
        <div
          className="absolute right-0 top-[calc(100%+0.5rem)] z-50 w-44 overflow-hidden rounded-2xl border border-white/10 bg-[#1c1c21]/95 p-1.5 shadow-2xl shadow-black/70 ring-1 ring-ark-line/80 backdrop-blur-xl"
          role="listbox"
          aria-label={ariaLabel}
        >
          {LANG_OPTIONS.map((option) => {
            const active = option.code === lang;
            return (
              <button
                key={option.code}
                type="button"
                role="option"
                aria-selected={active}
                onClick={() => {
                  setLang(option.code as Lang);
                  setOpen(false);
                }}
                className={`flex w-full items-center gap-2 rounded-xl px-3 py-2 text-left text-sm transition ${
                  active
                    ? "bg-ark-gold/10 text-ark-gold2"
                    : "text-neutral-200 hover:bg-white/10 hover:text-white"
                }`}
              >
                <FlagIcon code={option.code} className="h-5 w-5" />
                <span className="truncate font-medium">{option.label}</span>
              </button>
            );
          })}
        </div>
      ) : null}
    </div>
  );
}

export function PublicLayout() {
  const { t, lang, setLang } = useI18n();
  const { pathname, search, hash } = useLocation();
  const [open, setOpen] = useState(false);
  const [mobileSearchOpen, setMobileSearchOpen] = useState(false);
  const [q, setQ] = useState("");
  const nav = useNavigate();

  const na = (which: PublicNavWhich) =>
    navIsActive(pathname, search, hash, which);
  const isHome = pathname === "/";
  const footerInContentFlow =
    pathname === "/browse" || pathname.startsWith("/category/");

  const goSearch = () => {
    const s = q.trim();
    if (!s) return;
    nav(`/browse?q=${encodeURIComponent(s)}`);
    setOpen(false);
    setMobileSearchOpen(false);
  };

  return (
    <div className="min-h-full flex flex-col">
      <header className="sticky top-0 z-40 bg-[#08070c] backdrop-blur-md md:border-b md:border-ark-line md:bg-ark-nav/98">
        <div className="flex h-[64px] items-center justify-between bg-[#08070c] px-4 py-3 md:hidden">
          <Link
            to="/"
            className="flex h-8 shrink-0 items-center gap-2 rounded-sm text-[20px] font-black leading-5 tracking-tight text-ark-gold outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-[#08070c]"
            aria-label={t("brand")}
          >
            <ArkLogoMark className="h-8 w-8 shrink-0" />
            <span className="truncate text-ark-gold">{t("brand")}</span>
          </Link>

          <div className="flex h-[40px] w-[136px] shrink-0 items-center gap-[8px]">
            <button
              type="button"
              onClick={() => {
                setOpen(false);
                setMobileSearchOpen((value) => !value);
              }}
              className="flex h-[40px] w-[40px] items-center justify-center rounded-full bg-[#191921] outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-[#08070c]"
              aria-label={t("search")}
              aria-expanded={mobileSearchOpen}
            >
              <img
                src="/assets/ark-library/header-search.svg"
                alt=""
                className="h-6 w-6"
                width={24}
                height={24}
                aria-hidden
                draggable={false}
              />
            </button>
            <MobileLanguageButton
              lang={lang}
              setLang={setLang}
              ariaLabel={t("langLabel")}
              onOpen={() => {
                setOpen(false);
                setMobileSearchOpen(false);
              }}
            />
            <button
              type="button"
              className="inline-flex h-[40px] w-[40px] shrink-0 items-center justify-center rounded-full bg-[#191921] text-[#a8a9ae] outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-[#08070c]"
              onClick={() => {
                setMobileSearchOpen(false);
                setOpen((v) => !v);
              }}
              aria-label="menu"
              aria-expanded={open}
            >
              {open ? (
                <X size={24} strokeWidth={2.4} />
              ) : (
                <img
                  src="/assets/ark-library/header-menu.svg"
                  alt=""
                  className="h-6 w-6"
                  width={24}
                  height={24}
                  aria-hidden
                  draggable={false}
                />
              )}
            </button>
          </div>
        </div>

        {mobileSearchOpen ? (
          <div className="border-t border-white/10 bg-[#08070c] px-5 pb-3 md:hidden max-[360px]:px-3">
            <div className="flex h-11 items-center gap-2 rounded-full border border-[#2a2a31] bg-[#191921] px-4">
              <SearchIcon size={18} className="shrink-0 text-[#a8a9ae]" />
              <input
                value={q}
                onChange={(e) => setQ(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && goSearch()}
                placeholder={t("searchPlaceholder")}
                className="min-w-0 flex-1 bg-transparent text-sm text-neutral-100 outline-none placeholder:text-[#777985]"
              />
            </div>
          </div>
        ) : null}

        <div className="mx-auto hidden max-w-[1280px] px-4 py-[15px] min-[440px]:px-5 sm:px-6 md:block md:px-9 xl:px-0">
          {/* Single row (md+): logo | scrollable nav (左對齊，可橫向滑動) | 搜尋 + 語言 */}
          <div className="flex h-10 items-center gap-2 min-[1200px]:gap-0 lg:gap-4">
            <Link
              to="/"
              className="flex min-w-0 shrink-0 items-center gap-2.5 rounded-sm text-xl font-bold tracking-wide text-ark-gold outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg"
            >
              <ArkLogoMark className="h-10 w-10 shrink-0" />
              <span className="max-w-[8rem] truncate text-ark-gold sm:inline">
                {t("brand")}
              </span>
            </Link>

            <nav
              className="header-nav-scroll hidden min-w-0 flex-1 items-center justify-center gap-4 overflow-x-auto overflow-y-hidden py-1 min-[1200px]:flex lg:gap-5"
              aria-label={t("mainNav")}
            >
              <Link
                to="/browse"
                className={navClassName(na("browseAll"))}
                aria-current={na("browseAll") ? "page" : undefined}
              >
                {t("all")}
              </Link>
              <Link
                to="/#categories"
                className={navClassName(na("categories"))}
                aria-current={na("categories") ? "page" : undefined}
              >
                {t("categories")}
              </Link>
              <Link
                to="/#official"
                className={navClassName(na("browseRecommended"))}
                aria-current={na("browseRecommended") ? "page" : undefined}
              >
                {t("official")}
              </Link>
              <Link
                to="/#latest"
                className={navClassName(na("browseLatest"))}
                aria-current={na("browseLatest") ? "page" : undefined}
              >
                {t("latest")}
              </Link>
              <Link
                to="/#popular"
                className={navClassName(na("browsePopular"))}
                aria-current={na("browsePopular") ? "page" : undefined}
              >
                {t("popular")}
              </Link>
              <Link
                to="/about"
                className={navClassName(na("about"))}
                aria-current={na("about") ? "page" : undefined}
              >
                {t("footerAbout")}
              </Link>
            </nav>

            <div className="flex min-w-0 flex-1 items-center justify-end gap-2 min-[1200px]:flex-none">
              <div className="hidden h-10 min-w-0 flex-1 items-center gap-2 rounded-full border border-ark-line bg-[#1a1b20] py-2 pl-3 pr-3 shadow-inner md:flex min-[1200px]:w-44 min-[1200px]:flex-none lg:pr-4 xl:w-52">
                <SearchIcon size={16} className="shrink-0 text-[#c6c7cf]" />
                <input
                  value={q}
                  onChange={(e) => setQ(e.target.value)}
                  onKeyDown={(e) => e.key === "Enter" && goSearch()}
                  placeholder={t("searchPlaceholder")}
                  className="min-w-0 flex-1 rounded-md bg-transparent text-sm text-neutral-200 outline-none placeholder:text-[#777985] focus-visible:ring-2 focus-visible:ring-ark-gold/60 focus-visible:ring-offset-2 focus-visible:ring-offset-[#1a1b20]"
                />
              </div>
              <LanguageDropdown
                lang={lang}
                setLang={setLang}
                ariaLabel={t("langLabel")}
                className="hidden h-10 w-36 md:block lg:w-40"
              />
              <button
                type="button"
                className="inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-full border border-ark-line bg-[#1a1b20] text-neutral-200 outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg min-[1200px]:hidden"
                onClick={() => setOpen((v) => !v)}
                aria-label="menu"
              >
                {open ? <X size={18} /> : <Menu size={18} />}
              </button>
            </div>
          </div>
        </div>

        {open ? (
          <div className="grid gap-2 border-t border-ark-line bg-ark-nav px-4 py-3 min-[440px]:px-5 sm:px-6 md:px-9 min-[1200px]:hidden">
            <div className="mb-1 hidden items-center gap-2 rounded-full border border-ark-line bg-[#1a1b20] px-3 py-2 md:flex">
              <SearchIcon size={16} className="shrink-0 text-[#c6c7cf]" />
              <input
                value={q}
                onChange={(e) => setQ(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && goSearch()}
                placeholder={t("searchPlaceholder")}
                className="flex-1 bg-transparent text-sm outline-none placeholder:text-[#777985]"
              />
            </div>
            <LanguageDropdown
              lang={lang}
              setLang={setLang}
              ariaLabel={t("langLabel")}
              className="mb-1 hidden md:block"
            />
            <Link
              to="/browse"
              className={navClassName(na("browseAll"))}
              aria-current={na("browseAll") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("all")}
            </Link>
            <Link
              to="/#categories"
              className={navClassName(na("categories"))}
              aria-current={na("categories") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("categories")}
            </Link>
            <Link
              to="/#official"
              className={navClassName(na("browseRecommended"))}
              aria-current={na("browseRecommended") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("official")}
            </Link>
            <Link
              to="/#latest"
              className={navClassName(na("browseLatest"))}
              aria-current={na("browseLatest") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("latest")}
            </Link>
            <Link
              to="/#popular"
              className={navClassName(na("browsePopular"))}
              aria-current={na("browsePopular") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("popular")}
            </Link>
            <Link
              to="/about"
              className={navClassName(na("about"))}
              aria-current={na("about") ? "page" : undefined}
              onClick={() => setOpen(false)}
            >
              {t("footerAbout")}
            </Link>
          </div>
        ) : null}
      </header>

      <main
        className={`mx-auto w-full max-w-[1280px] ${
          isHome
            ? "flex-1 px-0 pb-6 pt-0 md:px-9 md:pb-10 md:pt-10 xl:px-0"
            : footerInContentFlow
              ? "px-0 pb-0 pt-0 md:px-9 md:pt-10 xl:px-0"
              : "flex-1 px-4 pb-6 pt-6 min-[440px]:px-5 sm:px-6 md:px-9 md:pb-10 md:pt-10 xl:px-0"
        }`}
      >
        <Outlet />
      </main>

      <footer className="mt-auto bg-transparent md:border-t md:border-ark-line md:bg-ark-nav/90">
        <div className="mx-auto flex h-[52px] max-w-[358px] items-center justify-center px-4 py-4 text-[13px] leading-5 md:h-auto md:max-w-[1280px] md:justify-start md:px-9 md:py-6 md:text-sm xl:px-0">
          <Link
            to="/about"
            className={`rounded-sm outline-none hover:text-ark-gold2 focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg ${
              na("about") ? "text-ark-gold" : "text-[#A8A9AE]"
            }`}
          >
            {t("footerAbout")}
          </Link>
        </div>
      </footer>

      <nav className="sticky inset-x-0 bottom-0 z-40 bg-[#0C0D0F]/90 backdrop-blur md:hidden">
        <div className="grid h-[78px] grid-cols-4 gap-3 px-5 py-4 text-center text-[11px] leading-[17.6px]">
          <BottomNavIcon
            to="/"
            label={t("home")}
            icon="home"
            active={pathname === "/"}
          />
          <BottomNavIcon
            to="/browse"
            label={t("all")}
            icon="document"
            active={
              pathname === "/browse" && !new URLSearchParams(search).get("sort")
            }
          />
          <BottomNavIcon
            to="/favorites"
            label={t("favorites")}
            icon="bookmark"
            active={pathname === "/favorites"}
          />
          <BottomNavIcon
            to="/#latest"
            label={t("latest")}
            icon="update"
            active={pathname === "/" && hash === "#latest"}
          />
        </div>
      </nav>
    </div>
  );
}

const NAVBAR_ICON_BASE = "/assets/ark-library/navbar";

function BottomNavIcon({
  to,
  label,
  icon,
  active,
}: {
  to: string;
  label: string;
  icon: "home" | "document" | "bookmark" | "update";
  active: boolean;
}) {
  const src = active
    ? `${NAVBAR_ICON_BASE}/${icon}-active.svg`
    : `${NAVBAR_ICON_BASE}/${icon}-inactive.svg`;
  return (
    <Link
      to={to}
      className={[
        "flex min-w-0 flex-col items-center gap-1 rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg",
        active ? "text-ark-gold" : "text-[#908F92]",
      ].join(" ")}
    >
      <img
        src={src}
        alt=""
        className="mx-auto h-6 w-6 object-contain"
        width={24}
        height={24}
        loading="lazy"
        decoding="async"
      />
      <span className="leading-tight">{label}</span>
    </Link>
  );
}
