"use client";

import { useMemo } from "react";
import { toast } from "sonner";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@multica/ui/components/ui/select";
import { useTheme, usePalette, type Palette } from "@multica/ui/components/common/theme-provider";
import { cn } from "@multica/ui/lib/utils";
import {
  DEFAULT_LOCALE,
  SUPPORTED_LOCALES,
  type SupportedLocale,
} from "@multica/core/i18n";
import { useLocaleAdapter } from "@multica/core/i18n/react";
import { useAuthStore } from "@multica/core/auth";
import { api } from "@multica/core/api";
import { browserTimezone, timezoneOptions } from "../../common/timezone-select";
import { useT } from "../../i18n";

const PALETTE_COLORS = {
  rime: {
    light: {
      titleBar: "#d0daf0",
      content: "#ebf0fa",
      sidebar: "#dce4f4",
      bar: "#4a6cc8",
      barMuted: "#b0bdd8",
    },
    dark: {
      titleBar: "#1e2048",
      content: "#16183a",
      sidebar: "#11132e",
      bar: "#d4833a",
      barMuted: "#353862",
    },
  },
  zinc: {
    light: {
      titleBar: "#e8e8e8",
      content: "#ffffff",
      sidebar: "#f4f4f5",
      bar: "#e4e4e7",
      barMuted: "#d4d4d8",
    },
    dark: {
      titleBar: "#333338",
      content: "#27272a",
      sidebar: "#1e1e21",
      bar: "#3f3f46",
      barMuted: "#52525b",
    },
  },
} as const;

const LIGHT_COLORS = PALETTE_COLORS.rime.light;
const DARK_COLORS = PALETTE_COLORS.rime.dark;

function WindowMockup({
  variant,
  className,
}: {
  variant: "light" | "dark";
  className?: string;
}) {
  const colors = variant === "light" ? LIGHT_COLORS : DARK_COLORS;

  return (
    <div className={cn("flex h-full w-full flex-col", className)}>
      {/* Title bar */}
      <div
        className="flex items-center gap-[3px] px-2 py-1.5"
        style={{ backgroundColor: colors.titleBar }}
      >
        <span className="size-[6px] rounded-full bg-[#ff5f57]" />
        <span className="size-[6px] rounded-full bg-[#febc2e]" />
        <span className="size-[6px] rounded-full bg-[#28c840]" />
      </div>
      {/* Content area */}
      <div
        className="flex flex-1"
        style={{ backgroundColor: colors.content }}
      >
        {/* Sidebar */}
        <div
          className="w-[30%] space-y-1 p-2"
          style={{ backgroundColor: colors.sidebar }}
        >
          <div
            className="h-1 w-3/4 rounded-full"
            style={{ backgroundColor: colors.bar }}
          />
          <div
            className="h-1 w-1/2 rounded-full"
            style={{ backgroundColor: colors.bar }}
          />
        </div>
        {/* Main */}
        <div className="flex-1 space-y-1.5 p-2">
          <div
            className="h-1.5 w-4/5 rounded-full"
            style={{ backgroundColor: colors.bar }}
          />
          <div
            className="h-1 w-full rounded-full"
            style={{ backgroundColor: colors.barMuted }}
          />
          <div
            className="h-1 w-3/5 rounded-full"
            style={{ backgroundColor: colors.barMuted }}
          />
        </div>
      </div>
    </div>
  );
}

function PaletteMockup({
  palette,
  className,
}: {
  palette: Palette;
  className?: string;
}) {
  const light = PALETTE_COLORS[palette].light;
  const dark = PALETTE_COLORS[palette].dark;

  return (
    <div className={cn("flex h-full w-full", className)}>
      {/* Light half */}
      <div className="flex w-1/2 flex-col">
        <div
          className="flex items-center gap-[3px] px-2 py-1.5"
          style={{ backgroundColor: light.titleBar }}
        >
          <span className="size-[6px] rounded-full bg-[#ff5f57]" />
          <span className="size-[6px] rounded-full bg-[#febc2e]" />
          <span className="size-[6px] rounded-full bg-[#28c840]" />
        </div>
        <div
          className="flex flex-1"
          style={{ backgroundColor: light.content }}
        >
          <div
            className="w-[30%] space-y-1 p-2"
            style={{ backgroundColor: light.sidebar }}
          >
            <div
              className="h-1 w-3/4 rounded-full"
              style={{ backgroundColor: light.bar }}
            />
            <div
              className="h-1 w-1/2 rounded-full"
              style={{ backgroundColor: light.bar }}
            />
          </div>
          <div className="flex-1 space-y-1.5 p-2">
            <div
              className="h-1.5 w-4/5 rounded-full"
              style={{ backgroundColor: light.bar }}
            />
            <div
              className="h-1 w-full rounded-full"
              style={{ backgroundColor: light.barMuted }}
            />
          </div>
        </div>
      </div>
      {/* Dark half */}
      <div className="flex w-1/2 flex-col">
        <div
          className="flex items-center justify-end gap-[3px] px-2 py-1.5"
          style={{ backgroundColor: dark.titleBar }}
        />
        <div
          className="flex flex-1"
          style={{ backgroundColor: dark.content }}
        >
          <div className="flex-1 space-y-1.5 p-2">
            <div
              className="h-1.5 w-4/5 rounded-full"
              style={{ backgroundColor: dark.bar }}
            />
            <div
              className="h-1 w-full rounded-full"
              style={{ backgroundColor: dark.barMuted }}
            />
          </div>
        </div>
      </div>
    </div>
  );
}

export function PreferencesTab() {
  const { theme, setTheme } = useTheme();
  const { palette, setPalette } = usePalette();
  const { t, i18n } = useT("settings");
  const localeAdapter = useLocaleAdapter();
  const user = useAuthStore((s) => s.user);

  // i18next.language can be a region-tagged BCP-47 string (e.g. "en-US",
  // "zh-Hans-CN") returned by intl-localematcher. Normalize to a supported
  // locale before comparing — otherwise the radio shows neither option active.
  const currentLocale: SupportedLocale = SUPPORTED_LOCALES.includes(
    i18n.language as SupportedLocale,
  )
    ? (i18n.language as SupportedLocale)
    : DEFAULT_LOCALE;

  const themeOptions = [
    { value: "light" as const, label: t(($) => $.preferences.theme.light) },
    { value: "dark" as const, label: t(($) => $.preferences.theme.dark) },
    { value: "system" as const, label: t(($) => $.preferences.theme.system) },
  ];

  const paletteOptions: { value: Palette; label: string; description: string }[] = [
    {
      value: "rime",
      label: t(($) => $.preferences.palette.rime),
      description: t(($) => $.preferences.palette.rime_description),
    },
    {
      value: "zinc",
      label: t(($) => $.preferences.palette.zinc),
      description: t(($) => $.preferences.palette.zinc_description),
    },
  ];

  const languageOptions: { value: SupportedLocale; label: string }[] = [
    { value: "en", label: t(($) => $.preferences.language.english) },
    { value: "zh-Hans", label: t(($) => $.preferences.language.chinese) },
    { value: "ko", label: t(($) => $.preferences.language.korean) },
    { value: "ja", label: t(($) => $.preferences.language.japanese) },
  ];

  // Persist locally → sync to user.language → reload. Reload (vs in-place
  // changeLanguage) avoids hydration mismatch and is the i18next-recommended
  // pattern for App Router.
  //
  // If the cross-device sync (PATCH /api/me) fails, the local cookie is
  // already written so the new locale will take effect after reload — but
  // the user's other devices won't see the change. Surface that explicitly
  // via a toast and delay the reload long enough for the toast to be read,
  // otherwise the failure would be invisible.
  const handleLanguageChange = async (next: SupportedLocale) => {
    if (next === currentLocale) return;
    localeAdapter.persist(next);

    let syncFailed = false;
    if (user) {
      try {
        await api.updateMe({ language: next });
      } catch {
        syncFailed = true;
      }
    }

    if (syncFailed) {
      toast.warning(t(($) => $.preferences.language.sync_failed));
      // Give the toast 2.5s of visible time before navigating away.
      setTimeout(() => window.location.reload(), 2500);
      return;
    }
    window.location.reload();
  };

  return (
    <div className="space-y-8">
      <section className="space-y-4">
        <h2 className="text-sm font-semibold">
          {t(($) => $.preferences.theme.title)}
        </h2>
        <div className="flex gap-6" role="radiogroup">
          {themeOptions.map((opt) => {
            const active = theme === opt.value;
            return (
              <button
                type="button"
                key={opt.value}
                role="radio"
                aria-checked={active}
                onClick={() => setTheme(opt.value)}
                className="group flex flex-col items-center gap-2"
              >
                <div
                  className={cn(
                    "aspect-[4/3] w-36 overflow-hidden rounded-lg ring-1 transition-all",
                    active
                      ? "ring-2 ring-brand"
                      : "ring-border hover:ring-2 hover:ring-border"
                  )}
                >
                  {opt.value === "system" ? (
                    <div className="relative h-full w-full">
                      <WindowMockup
                        variant="light"
                        className="absolute inset-0"
                      />
                      <WindowMockup
                        variant="dark"
                        className="absolute inset-0 [clip-path:inset(0_0_0_50%)]"
                      />
                    </div>
                  ) : (
                    <WindowMockup variant={opt.value} />
                  )}
                </div>
                <span
                  className={cn(
                    "text-sm transition-colors",
                    active
                      ? "font-medium text-foreground"
                      : "text-muted-foreground"
                  )}
                >
                  {opt.label}
                </span>
              </button>
            );
          })}
        </div>
      </section>

      <section className="space-y-4">
        <h2 className="text-sm font-semibold">
          {t(($) => $.preferences.palette.title)}
        </h2>
        <div className="flex gap-6" role="radiogroup">
          {paletteOptions.map((opt) => {
            const active = palette === opt.value;
            return (
              <button
                type="button"
                key={opt.value}
                role="radio"
                aria-checked={active}
                onClick={() => setPalette(opt.value)}
                className="group flex flex-col items-center gap-2"
              >
                <div
                  className={cn(
                    "aspect-[4/3] w-36 overflow-hidden rounded-lg ring-1 transition-all",
                    active
                      ? "ring-2 ring-brand"
                      : "ring-border hover:ring-2 hover:ring-border"
                  )}
                >
                  <PaletteMockup palette={opt.value} />
                </div>
                <div className="flex flex-col items-center">
                  <span
                    className={cn(
                      "text-sm transition-colors",
                      active
                        ? "font-medium text-foreground"
                        : "text-muted-foreground"
                    )}
                  >
                    {opt.label}
                  </span>
                  <span className="text-xs text-muted-foreground">
                    {opt.description}
                  </span>
                </div>
              </button>
            );
          })}
        </div>
      </section>

      <section className="space-y-4">
        <h2 className="text-sm font-semibold">
          {t(($) => $.preferences.language.title)}
        </h2>
        <div className="flex gap-3" role="radiogroup">
          {languageOptions.map((opt) => {
            const active = currentLocale === opt.value;
            return (
              <button
                type="button"
                key={opt.value}
                role="radio"
                aria-checked={active}
                onClick={() => handleLanguageChange(opt.value)}
                className={cn(
                  "rounded-md border px-4 py-2 text-sm transition-colors",
                  active
                    ? "border-brand bg-brand/10 font-medium text-foreground"
                    : "border-border text-muted-foreground hover:border-foreground/30"
                )}
              >
                {opt.label}
              </button>
            );
          })}
        </div>
      </section>

      <TimezoneSection />
    </div>
  );
}

// Base UI rejects "" as a SelectItem value, so route the "no preference"
// state through this sentinel and translate at the wire boundary.
const BROWSER_TZ_VALUE = "__browser__";

function TimezoneSection() {
  const { t } = useT("settings");
  const user = useAuthStore((s) => s.user);
  const setUser = useAuthStore((s) => s.setUser);
  const stored = user?.timezone ?? null;
  const browser = browserTimezone();
  const value = stored ?? BROWSER_TZ_VALUE;

  // Full IANA list (from timezoneOptions in common/timezone-select) so a
  // user needing a non-curated zone isn't stuck with ~18 common ones.
  // Memoized — timezoneOptions enumerates ~600 IANA zones per call.
  const options = useMemo(
    () => timezoneOptions(stored ?? browser),
    [stored, browser],
  );

  const handleChange = async (next: string) => {
    if (next === value) return;
    const payload = next === BROWSER_TZ_VALUE ? "" : next;
    try {
      const updated = await api.updateMe({ timezone: payload });
      setUser(updated);
    } catch (err) {
      toast.error(
        err instanceof Error && err.message
          ? err.message
          : t(($) => $.preferences.timezone.sync_failed),
      );
    }
  };

  const formatTZLabel = (tz: string) => {
    if (tz === BROWSER_TZ_VALUE) {
      return `${browser}${t(($) => $.preferences.timezone.browser_suffix)}`;
    }
    return tz;
  };

  return (
    <section className="space-y-2">
      <h2 className="text-sm font-semibold">
        {t(($) => $.preferences.timezone.title)}
      </h2>
      <Select
        value={value}
        onValueChange={(next) => {
          if (next) handleChange(next);
        }}
      >
        <SelectTrigger size="sm" className="w-72 rounded-md font-mono text-xs">
          <SelectValue>{formatTZLabel(value)}</SelectValue>
        </SelectTrigger>
        <SelectContent align="start" className="max-h-72">
          <SelectItem value={BROWSER_TZ_VALUE} className="font-mono text-xs">
            {formatTZLabel(BROWSER_TZ_VALUE)}
          </SelectItem>
          {options.map((tz) => (
            <SelectItem key={tz} value={tz} className="font-mono text-xs">
              {formatTZLabel(tz)}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
      <p className="text-[11px] leading-snug text-muted-foreground">
        {t(($) => $.preferences.timezone.hint)}
      </p>
    </section>
  );
}
