import { useEffect, useState } from "react";
import { PageHeader } from "../components/layout/PageHeader";
import { DevModeSessionCard } from "../components/settings/DevModeSessionCard";
import { Button, Card, Input, Select } from "../components/ui";
import { useData, useRepos } from "../data/DataContext";
import type { AiSettings, PlacementSettings } from "../domain/types";
import { useI18n } from "../i18n/I18nContext";
import { CURRENCIES, LOCALES, type AppCurrency, type AppLocale } from "../lib/i18n/types";
import type { ThemePreference } from "../lib/theme";
import { useTheme } from "../theme/ThemeContext";

/** 可選 provider；文案／研究／延伸共用目前選中的那一組 */
const AI_PROVIDERS = [
  { id: "xai", label: "xAI" },
  { id: "opencode-go", label: "OpenCode Go" },
] as const;

type AiProviderId = (typeof AI_PROVIDERS)[number]["id"];

function normalizeProvider(id: string): AiProviderId {
  return id === "opencode-go" ? "opencode-go" : "xai";
}

export function SettingsPage() {
  const repos = useRepos();
  const { refresh } = useData();
  const { t, locale, currency, setPrefs } = useI18n();
  const { preference, setPreference } = useTheme();

  const [ai, setAi] = useState<AiSettings | null>(null);
  const [placement, setPlacement] = useState<PlacementSettings | null>(null);
  const [apiKey, setApiKey] = useState("");
  const [exaKey, setExaKey] = useState("");
  const [models, setModels] = useState<string[]>([]);
  const [message, setMessage] = useState("");
  const [error, setError] = useState("");
  const [busy, setBusy] = useState("");
  const [draftLocale, setDraftLocale] = useState<AppLocale>(locale);
  const [draftCurrency, setDraftCurrency] = useState<AppCurrency>(currency);

  useEffect(() => {
    setDraftLocale(locale);
    setDraftCurrency(currency);
  }, [locale, currency]);

  /** 進頁：一支 GetAi 同時拿設定 + 模型清單 + 上次選定 model */
  useEffect(() => {
    void (async () => {
      let a: AiSettings;
      let p: PlacementSettings;
      try {
        a = await repos.settings.getAi();
        p = await repos.settings.getPlacement();
      } catch (e) {
        // ai 留 null → 整個設定表單不渲染，沒有訊息的話畫面會是一片空白。
        setError(e instanceof Error ? e.message : t("settings.loadFail"));
        return;
      }
      const provider = normalizeProvider(a.provider);
      const list = a.models?.length
        ? a.models
        : [a.selected_model || a.model].filter(Boolean) as string[];
      const model =
        a.selected_model && list.includes(a.selected_model)
          ? a.selected_model
          : list.includes(a.model)
            ? a.model
            : list[0] || a.model;
      setModels(list);
      setAi({
        ...a,
        provider,
        model,
        research_provider: provider,
        research_model: model,
        selected_model: model,
        models: list,
      });
      setPlacement(p);
      setError(a.models_error || "");
    })();
  }, [repos.settings, t]);

  /** 換 provider：同一支 getAi(?provider=) 帶回 models + selected_model */
  async function onProviderChange(nextId: string) {
    if (!ai) return;
    const provider = normalizeProvider(nextId);
    setBusy("ai");
    setError("");
    try {
      const a = await repos.settings.getAi(provider);
      const list = a.models?.length
        ? a.models
        : [a.selected_model || a.model].filter(Boolean) as string[];
      const model =
        a.selected_model && list.includes(a.selected_model)
          ? a.selected_model
          : list.includes(ai.model)
            ? ai.model
            : list[0] || ai.model;
      setModels(list);
      setAi({
        ...ai,
        ...a,
        provider,
        model,
        research_provider: provider,
        research_model: model,
        selected_model: model,
        models: list,
      });
      if (a.models_error) setError(a.models_error);
    } catch (e) {
      setError(e instanceof Error ? e.message : t("common.error"));
    } finally {
      setBusy("");
    }
  }

  async function saveAi() {
    if (!ai) return;
    setBusy("ai");
    setError("");
    try {
      const provider = normalizeProvider(ai.provider);
      // 同一 provider + 同一 model；save 回傳仍含 models
      const next = await repos.settings.saveAi({
        provider,
        model: ai.model,
        research_provider: provider,
        research_model: ai.model,
        api_key: apiKey || undefined,
        research_api_key: apiKey || undefined,
      });
      const list = next.models?.length ? next.models : models;
      const model = next.selected_model || next.model || ai.model;
      setModels(list);
      setAi({
        ...next,
        provider: normalizeProvider(next.provider),
        model,
        research_provider: normalizeProvider(next.provider),
        research_model: model,
        selected_model: model,
        models: list,
      });
      setApiKey("");
      setMessage(t("settings.aiSaved"));
      if (next.models_error) setError(next.models_error);
      refresh();
    } catch (e) {
      setError(e instanceof Error ? e.message : t("common.error"));
    } finally {
      setBusy("");
    }
  }

  async function clearAiKey() {
    if (!ai) return;
    setBusy("ai-clear");
    setMessage("");
    setError("");
    try {
      const next = await repos.settings.saveAi({
        provider: normalizeProvider(ai.provider),
        api_key_configured: false,
        research_api_key_configured: false,
      });
      setAi({ ...ai, ...next });
      setApiKey("");
      setMessage(t("settings.aiKeyCleared"));
      refresh();
    } catch (e) {
      setError(e instanceof Error ? e.message : t("common.error"));
    } finally {
      setBusy("");
    }
  }

  async function savePlacement() {
    if (!placement) return;
    setBusy("placement");
    try {
      const next = await repos.settings.savePlacement({
        ...placement,
        web_search_provider: "exa",
        exa_api_key: exaKey || undefined,
      });
      setPlacement(next);
      setExaKey("");
      setMessage(t("settings.searchSaved"));
      refresh();
    } catch (e) {
      setError(e instanceof Error ? e.message : t("common.error"));
    } finally {
      setBusy("");
    }
  }

  async function clearExaKey() {
    if (!placement) return;
    setBusy("placement-clear");
    setMessage("");
    setError("");
    try {
      const next = await repos.settings.savePlacement({ exa_api_key_configured: false });
      setPlacement(next);
      setExaKey("");
      setMessage(t("settings.exaKeyCleared"));
      refresh();
    } catch (e) {
      setError(e instanceof Error ? e.message : t("common.error"));
    } finally {
      setBusy("");
    }
  }

  function saveLocaleCurrency() {
    setPrefs({ locale: draftLocale, currency: draftCurrency });
    setMessage(t("settings.localeSaved"));
  }

  function pickTheme(next: ThemePreference) {
    setPreference(next);
    setMessage(t("settings.themeSaved"));
  }

  const modelOptions = models.length ? models : [ai?.model || ai?.selected_model].filter(Boolean) as string[];

  return (
    <>
      <PageHeader title={t("settings.title")} />

      {message ? (
        <p className="hb-banner-ok" role="status">
          {message}
        </p>
      ) : null}
      {error ? (
        <p className="hb-form-error" role="alert">
          {error}
        </p>
      ) : null}

      <Card title={t("settings.appearance")}>
        <div className="hb-stack">
          <p className="hb-field__label" style={{ margin: 0 }}>
            {t("settings.theme")}
          </p>
          <div className="hb-theme-picker" role="group" aria-label={t("settings.theme")}>
            {(
              [
                ["light", t("settings.themeLight")],
                ["dark", t("settings.themeDark")],
                ["system", t("settings.themeSystem")],
              ] as const
            ).map(([id, label]) => (
              <button
                key={id}
                type="button"
                className={`hb-theme-picker__btn${preference === id ? " is-active" : ""}`}
                onClick={() => pickTheme(id)}
              >
                <span className={`hb-theme-picker__swatch hb-theme-picker__swatch--${id}`} aria-hidden />
                {label}
              </button>
            ))}
          </div>
        </div>
      </Card>

      <Card title={t("settings.localeCurrency")}>
        <div className="hb-stack">
          <div className="hb-grid-2">
            <Select
              label={t("settings.locale")}
              value={draftLocale}
              onChange={(e) => setDraftLocale(e.target.value as AppLocale)}
            >
              {LOCALES.map((l) => (
                <option key={l.id} value={l.id}>
                  {t(`locale.${l.id}`)}
                </option>
              ))}
            </Select>
            <Select
              label={t("settings.currency")}
              value={draftCurrency}
              onChange={(e) => setDraftCurrency(e.target.value as AppCurrency)}
            >
              {CURRENCIES.map((c) => (
                <option key={c.id} value={c.id}>
                  {t(`currency.${c.id}`)}
                </option>
              ))}
            </Select>
          </div>
          <Button type="button" onClick={saveLocaleCurrency}>
            {t("common.save")}
          </Button>
        </div>
      </Card>

      <Card title={t("settings.ai")}>
        {ai ? (
          <div className="hb-stack">
            <p className="text-muted" style={{ margin: 0, fontSize: "var(--hb-text-sm)" }}>
              {t("settings.aiUnifiedHint")}
            </p>
            <Select
              label={t("settings.provider")}
              value={normalizeProvider(ai.provider)}
              onChange={(e) => void onProviderChange(e.target.value)}
            >
              {AI_PROVIDERS.map((p) => (
                <option key={p.id} value={p.id}>
                  {p.label}
                </option>
              ))}
            </Select>
            <Select
              label={t("settings.model")}
              value={ai.model}
              disabled={busy === "ai" && models.length === 0}
              onChange={(e) => {
                const provider = normalizeProvider(ai.provider);
                setAi({
                  ...ai,
                  provider,
                  model: e.target.value,
                  research_provider: provider,
                  research_model: e.target.value,
                });
              }}
            >
              {modelOptions.map((m) => (
                <option key={m} value={m}>
                  {m}
                </option>
              ))}
            </Select>
            <Input
              label={t("settings.apiKey")}
              type="password"
              value={apiKey}
              onChange={(e) => setApiKey(e.target.value)}
              placeholder={
                ai.api_key_configured || ai.research_api_key_configured
                  ? t("settings.configured")
                  : ai.platform_key_available
                    ? t("settings.platformKeyOk")
                    : t("settings.notConfigured")
              }
            />
            {ai.models_error ? (
              <p className="text-muted" style={{ margin: 0, fontSize: "var(--hb-text-sm)" }}>
                {t("settings.modelsHint")}: {ai.models_error}
              </p>
            ) : ai.models_from_cache ? (
              <p className="text-muted" style={{ margin: 0, fontSize: "var(--hb-text-sm)" }}>
                {t("settings.modelsCached")}
              </p>
            ) : null}
            <div className="hb-wizard-actions">
              <Button type="button" onClick={() => void saveAi()} disabled={Boolean(busy)}>
                {t("common.save")}
              </Button>
              <Button
                type="button"
                variant="danger"
                onClick={() => void clearAiKey()}
                disabled={Boolean(busy) || (!ai.api_key_configured && !ai.research_api_key_configured)}
              >
                {busy === "ai-clear" ? t("common.loading") : t("settings.clearAiKey")}
              </Button>
            </div>
          </div>
        ) : (
          <p className="text-muted">{t("common.loading")}</p>
        )}
      </Card>

      <Card title={t("settings.search")}>
        {placement ? (
          <div className="hb-stack">
            <Input label={t("settings.searchProvider")} value="Exa" readOnly disabled />
            <Input
              label={t("settings.exaKey")}
              type="password"
              value={exaKey}
              onChange={(e) => setExaKey(e.target.value)}
              placeholder={
                placement.exa_api_key_configured
                  ? t("settings.configured")
                  : t("settings.notConfigured")
              }
            />
            <Select
              label={t("settings.expand")}
              value={placement.expand_strategy === "brave" ? "hybrid" : placement.expand_strategy}
              onChange={(e) =>
                setPlacement({
                  ...placement,
                  web_search_provider: "exa",
                  expand_strategy: e.target.value as PlacementSettings["expand_strategy"],
                })
              }
            >
              <option value="llm">LLM</option>
              <option value="hybrid">Hybrid</option>
            </Select>
            <div className="hb-stack hb-stack--tight" data-testid="settings-lab">
              <label className="hb-check-row">
                <input
                  type="checkbox"
                  checked={placement.dev_mode_enabled}
                  onChange={(e) =>
                    setPlacement({ ...placement, dev_mode_enabled: e.target.checked })
                  }
                />
                <span>{t("settings.devMode")}</span>
              </label>
              <p className="text-muted hb-settings-dev-hint">{t("settings.devModeHint")}</p>
              {placement.dev_mode_enabled ? (
                <DevModeSessionCard
                  onMessage={(msg) => {
                    setError("");
                    setMessage(msg);
                  }}
                  onError={(msg) => {
                    setMessage("");
                    setError(msg);
                  }}
                />
              ) : null}
            </div>
            <div className="hb-wizard-actions">
              <Button type="button" onClick={() => void savePlacement()} disabled={Boolean(busy)}>
                {t("common.save")}
              </Button>
              <Button
                type="button"
                variant="danger"
                onClick={() => void clearExaKey()}
                disabled={Boolean(busy) || !placement.exa_api_key_configured}
              >
                {busy === "placement-clear" ? t("common.loading") : t("settings.clearExaKey")}
              </Button>
            </div>
          </div>
        ) : (
          <p className="text-muted">{t("common.loading")}</p>
        )}
      </Card>
    </>
  );
}
