"use client";

import "@/i18n";

import { ChevronDown, Globe } from "lucide-react";
import { useMemo, useState, type ReactNode } from "react";
import { useTranslation } from "react-i18next";

import { useI18nHydrated } from "@/components/i18n-hydration-provider";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import zhCommon from "@/i18n/locales/zh/common.json";
import {
  DEFAULT_LANGUAGE,
  normalizeLanguage,
  SUPPORTED_LANGUAGES,
  type AppLanguage,
} from "@/i18n";
import { playerViewportPopoverMaxClass } from "@/lib/player-viewport";
import { cn } from "@/lib/utils";

interface LanguageSwitcherProps {
  variant?: "default" | "header" | "minimal" | "pill";
  /** 下拉相对触发器水平对齐：`start`=左对齐（适合左上角触发器），`end`=右对齐（适合顶栏右侧） */
  menuAlign?: "start" | "end";
  className?: string;
  showFlag?: boolean;
  showLabel?: boolean;
  /** 显示完整语言名（如「简体中文」），而非缩写 */
  useFullLabel?: boolean;
}

export function LanguageSwitcher({
  variant = "default",
  menuAlign,
  className,
  showFlag = true,
  showLabel = true,
  useFullLabel = false,
}: LanguageSwitcherProps) {
  const { i18n, t } = useTranslation("common");
  const active = normalizeLanguage(i18n.language) as AppLanguage;
  const [isOpen, setIsOpen] = useState(false);
  const mounted = useI18nHydrated();

  const options = useMemo(
    () =>
      SUPPORTED_LANGUAGES.map((item) => ({
        ...item,
        label: t(`language.${item.code}`),
        short: t(`languageShort.${item.code}`),
      })),
    [t],
  );

  async function handleSelect(code: AppLanguage): Promise<void> {
    await i18n.changeLanguage(code);
    setIsOpen(false);
  }

  const displayLang = mounted ? active : DEFAULT_LANGUAGE;
  const currentLabel = mounted
    ? useFullLabel
      ? (options.find((o) => o.code === displayLang)?.label ?? displayLang.toUpperCase())
      : (options.find((o) => o.code === displayLang)?.short ?? displayLang.toUpperCase())
    : useFullLabel
      ? zhCommon.language[displayLang]
      : zhCommon.languageShort[displayLang];
  const currentFlag = options.find((o) => o.code === active)?.flag ?? "";

  const variantStyles = {
    default: {
      button: "border border-white/20 bg-white/10 text-white hover:bg-white/20",
      dropdown: "border border-gray-200 bg-white shadow-lg",
      item: "text-gray-800 hover:bg-gray-100",
      activeItem: "bg-red-50 text-red-600",
    },
    header: {
      button: "text-white/80 hover:bg-white/10 hover:text-white",
      dropdown: "border border-white/20 bg-white/95 shadow-xl backdrop-blur-sm",
      item: "text-gray-800 hover:bg-white/10",
      activeItem: "bg-red-500/10 text-red-600",
    },
    minimal: {
      button: "text-current hover:bg-black/5",
      dropdown: "border border-gray-200 bg-white shadow-lg",
      item: "text-gray-800 hover:bg-gray-100",
      activeItem: "bg-red-50 text-red-600",
    },
    pill: {
      button:
        "rounded-full border border-gray-200 bg-white px-3 py-1.5 text-gray-600 shadow-sm hover:bg-gray-50",
      dropdown: "border border-gray-200 bg-white shadow-lg",
      item: "text-gray-800 hover:bg-gray-100",
      activeItem: "bg-red-50 text-red-600",
    },
  } as const;

  const styles = variantStyles[variant];

  const align =
    menuAlign ??
    (variant === "pill" ? "end" : variant === "header" || variant === "default" ? "start" : "end");

  return (
    <Popover open={isOpen} onOpenChange={setIsOpen}>
      <PopoverTrigger
        className={cn("inline-flex", className)}
        render={
          <button
            type="button"
            className={cn(
              "flex items-center gap-1.5 rounded-md px-2 py-1.5 text-sm font-medium transition-colors",
              styles.button,
            )}
            aria-expanded={isOpen}
            aria-haspopup="listbox"
            aria-label={`Language (${currentLabel})`}
          >
            <Globe className="size-4" aria-hidden />
            {showFlag && currentFlag ? <span className="text-base">{currentFlag}</span> : null}
            {showLabel ? (
              <span suppressHydrationWarning>{currentLabel}</span>
            ) : null}
            <ChevronDown
              className={cn("size-4 transition-transform duration-200", isOpen && "rotate-180")}
              aria-hidden
            />
          </button>
        }
      />
      <PopoverContent
        align={align}
        side="bottom"
        sideOffset={6}
        className={cn(
          "z-[200] w-auto min-w-[12rem] p-1 text-gray-900",
          playerViewportPopoverMaxClass,
          styles.dropdown,
        )}
      >
        <div className="max-h-[min(280px,50dvh)] overflow-y-auto" role="listbox">
          {options.map((option) => (
            <button
              key={option.code}
              type="button"
              onClick={() => void handleSelect(option.code)}
              className={cn(
                "flex w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm transition-colors",
                active === option.code ? styles.activeItem : styles.item,
              )}
              role="option"
              aria-selected={active === option.code}
            >
              <span className="text-lg">{option.flag}</span>
              <div className="flex flex-col leading-tight">
                <span className="font-medium">{option.label}</span>
                <span className="text-xs opacity-60">{option.short}</span>
              </div>
              {active === option.code ? (
                <svg
                  className="ml-auto size-4 text-red-500"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                  strokeWidth={2}
                  aria-hidden
                >
                  <path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
                </svg>
              ) : null}
            </button>
          ))}
        </div>
      </PopoverContent>
    </Popover>
  );
}

export function LanguageSwitcherMinimal({
  className,
}: {
  className?: string;
}): ReactNode {
  return (
    <LanguageSwitcher
      variant="minimal"
      menuAlign="end"
      className={className}
      showFlag={false}
    />
  );
}
