import { useEffect, useState } from "react";
import { api, CapabilityData, PublishGuardPolicy, ThreadsAccount, ThreadsAiSettings, ThreadsConnection, ThreadsDiagnostics } from "../api/haixun";
import { DevToolsPanel } from "../components/DevToolsPanel";
import { Badge, Button, Card, ErrorText, Field, Input, PageTitle, Select } from "../components/ui";
import { persistActiveThreadsAccountId } from "../lib/activeAccount";
import { formatNano } from "../lib/format";
import {
  consumeOAuthReturnMessage,
  markOAuthPending,
  pendingOAuthMessage,
} from "../lib/threadsOAuth";

export function AccountsPage() {
  const [accounts, setAccounts] = useState<ThreadsAccount[]>([]);
  const [activeId, setActiveId] = useState("");
  const [caps, setCaps] = useState<CapabilityData>();
  const [connection, setConnection] = useState<ThreadsConnection>();
  const [aiSettings, setAiSettings] = useState<ThreadsAiSettings>();
  const [diagnostics, setDiagnostics] = useState<ThreadsDiagnostics>();
  const [guard, setGuard] = useState<PublishGuardPolicy>();
  const [oauthEnabled, setOauthEnabled] = useState(false);
  const [oauthRequiresHttps, setOauthRequiresHttps] = useState(false);
  const [creating, setCreating] = useState(false);
  const [newName, setNewName] = useState("");
  const [apiKey, setApiKey] = useState("");
  const [provider, setProvider] = useState("opencode-go");
  const [model, setModel] = useState("");
  const [researchProvider, setResearchProvider] = useState("opencode-go");
  const [researchModel, setResearchModel] = useState("");
  const [modelsByProvider, setModelsByProvider] = useState<Record<string, string[]>>({});
  const [loadingModels, setLoadingModels] = useState("");
  const [devModeEnabled, setDevModeEnabled] = useState(false);
  const [error, setError] = useState<unknown>();
  const [message, setMessage] = useState("");

  async function load(preferredActiveId?: string) {
    setError(undefined);
    try {
      const [accountData, capData, oauth, placementSettings] = await Promise.all([
        api.threadsAccounts(),
        api.capabilities(),
        api.oauthConfig(),
        api.placementSettings(),
      ]);
      setDevModeEnabled(Boolean((placementSettings as { dev_mode_enabled?: boolean })?.dev_mode_enabled));
      setAccounts(accountData.list || []);
      setCaps(capData);
      setOauthEnabled(oauth.enabled);
      setOauthRequiresHttps(oauth.requires_https);
      const returnMessage = consumeOAuthReturnMessage();
      if (returnMessage) setMessage(returnMessage);
      else {
        const pendingMessage = pendingOAuthMessage();
        if (pendingMessage) setMessage(pendingMessage);
      }
      const currentActive = preferredActiveId !== undefined ? preferredActiveId : activeId;
      const id = currentActive || capData.active_threads_account_id || accountData.active_account_id || accountData.list?.[0]?.id || "";
      setActiveId(id);
      persistActiveThreadsAccountId(id);
      if (id) {
        const [conn, ai, diag, guardData] = await Promise.all([api.getThreadsConnection(id), api.threadsAiSettings(id), api.threadsDiagnostics(id), api.publishGuardPolicy(id)]);
        setConnection(conn);
        setAiSettings(ai);
        setDiagnostics(diag);
        setGuard(guardData);
        setProvider(ai.provider || "opencode-go");
        setModel(ai.model || "");
        setResearchProvider(ai.research_provider || ai.provider || "opencode-go");
        setResearchModel(ai.research_model || ai.model || "");
      } else {
        setConnection(undefined);
        setAiSettings(undefined);
        setDiagnostics(undefined);
        setGuard(undefined);
      }
    } catch (err) {
      setError(err);
    }
  }

  useEffect(() => {
    void load();
  }, []);

  useEffect(() => {
    function onPlacementSettingsChanged(event: Event) {
      const detail = (event as CustomEvent<{ dev_mode_enabled?: boolean }>).detail;
      if (detail?.dev_mode_enabled !== undefined) {
        setDevModeEnabled(detail.dev_mode_enabled);
      }
    }
    window.addEventListener("haixun:placement-settings-changed", onPlacementSettingsChanged);
    return () => window.removeEventListener("haixun:placement-settings-changed", onPlacementSettingsChanged);
  }, []);

  async function redirectToOAuth(accountId: string) {
    const data = await api.startOauth(accountId);
    const targetId = data.account_id || accountId;
    markOAuthPending(targetId);
    persistActiveThreadsAccountId(targetId);
    window.location.href = data.authorize_url;
  }

  async function createAccount() {
    setCreating(true);
    setError(undefined);
    try {
      const created = await api.createThreadsAccount({ display_name: newName || "巡樓帳號", activate: accounts.length === 0 });
      setNewName("");
      setActiveId(created.id);
      persistActiveThreadsAccountId(created.id);
      window.dispatchEvent(new CustomEvent("haixun:active-account-changed"));
      if (oauthEnabled) {
        await redirectToOAuth(created.id);
        return;
      }
      setMessage("帳號已建立。後端尚未設定 Threads OAuth（THREADS_APP_ID / SECRET / REDIRECT_URI），請補設定後再按「開始 OAuth」連線。");
      await load(created.id);
    } catch (err) {
      setError(err);
    } finally {
      setCreating(false);
    }
  }

  async function activate(id: string) {
    await api.activateThreadsAccount(id);
    setActiveId(id);
    window.dispatchEvent(new CustomEvent("haixun:active-account-changed"));
    await load(id);
  }

  async function deleteAccount(account: ThreadsAccount) {
    const label = account.display_name || account.username || account.id;
    const result = await api.deleteThreadsAccount(account.id);
    setMessage(result.message || `已刪除帳號：${label}`);
    setActiveId(result.active_account_id || "");
    setConnection(undefined);
    setAiSettings(undefined);
    setDiagnostics(undefined);
    setGuard(undefined);
    window.dispatchEvent(new CustomEvent("haixun:active-account-changed"));
    await load(result.active_account_id || "");
  }

  async function startOauth() {
    if (!activeId) return;
    setError(undefined);
    try {
      await redirectToOAuth(activeId);
    } catch (err) {
      setError(err);
    }
  }

  async function saveConnection() {
    if (!activeId || !connection) return;
    await api.updateThreadsConnection(activeId, connection.prefs);
    setMessage("連線偏好已儲存");
    await load();
  }

  async function saveAi() {
    if (!activeId) return;
    const api_keys = apiKey ? { [provider]: apiKey } : undefined;
    await api.updateThreadsAiSettings(activeId, {
      provider,
      model,
      research_provider: researchProvider,
      research_model: researchModel,
      api_keys
    });
    setApiKey("");
    setMessage("AI 設定已儲存");
    await load();
  }

  async function fetchModels(target: "copy" | "research") {
    if (!activeId) return;
    const targetProvider = target === "copy" ? provider : researchProvider;
    setLoadingModels(target);
    try {
      const data = await api.threadsAccountProviderModels(activeId, targetProvider, apiKey);
      setModelsByProvider((current) => ({ ...current, [targetProvider]: data.models || [] }));
      if (data.models?.length) {
        if (target === "copy" && !model) setModel(data.models[0]);
        if (target === "research" && !researchModel) setResearchModel(data.models[0]);
      }
      setMessage(data.error ? `模型清單取得完成，但 provider 回報：${data.error}` : `已取得 ${data.label} 模型清單`);
    } finally {
      setLoadingModels("");
    }
  }

  async function smokeTest() {
    if (!activeId) return;
    await api.smokeTest(activeId);
    const data = await api.threadsDiagnostics(activeId);
    setDiagnostics(data);
    setMessage("API 診斷已更新");
  }

  async function resumeGuard() {
    if (!activeId) return;
    const saved = await api.resumePublishGuard(activeId);
    setGuard(saved);
    setMessage("已解除此帳號發文暫停");
  }

  return (
    <div className="page-grid">
      <PageTitle title="Threads 帳號" subtitle="多帳號、OAuth、AI key、發文偏好集中在這裡設定。" action={<Button onClick={() => void load()}>重新載入</Button>} />
      <ErrorText error={error} />
      {message ? <Card><pre style={{ whiteSpace: "pre-wrap" }}>{message}</pre></Card> : null}

      <div className="grid-2">
        <Card title="帳號列表">
          <div className="page-grid">
            <div className="button-row">
              <Input value={newName} onChange={(e) => setNewName(e.target.value)} placeholder="帳號顯示名稱" />
              <Button variant="primary" loading={creating} onClick={() => void createAccount()}>
                {oauthEnabled ? "建立並連線 Threads" : "建立帳號"}
              </Button>
            </div>
            {accounts.map((account) => (
              <div
                key={account.id}
                className="card"
                role="button"
                tabIndex={0}
                style={{ textAlign: "left", cursor: "pointer" }}
                onClick={() => {
                  setActiveId(account.id);
                  void load(account.id);
                }}
                onKeyDown={(e) => {
                  if (e.key === "Enter" || e.key === " ") {
                    setActiveId(account.id);
                    void load(account.id);
                  }
                }}
              >
                <div className="button-row" style={{ justifyContent: "space-between" }}>
                  <strong>{account.display_name || account.username || account.id}</strong>
                  <Badge variant={account.id === activeId ? "brand" : "neutral"}>{account.id === activeId ? "使用中" : account.status}</Badge>
                </div>
                <p className="muted" style={{ margin: "0.4rem 0 0" }}>
                  API {account.api_connected ? "已連線" : "未連線"}
                  {devModeEnabled ? `，Chrome ${account.browser_connected ? "已同步" : "未同步"}` : ""}
                  ，token 到期 {formatNano(account.api_token_expires_at)}
                </p>
                <div className="button-row">
                  {account.id !== activeId ? <Button variant="soft" onClick={(e) => { e.preventDefault(); e.stopPropagation(); void activate(account.id); }}>設為使用中</Button> : null}
                  <Button variant="danger" onClick={(e) => { e.preventDefault(); e.stopPropagation(); void deleteAccount(account); }}>刪除帳號與資料</Button>
                </div>
              </div>
            ))}
            {accounts.length === 0 ? <p className="muted">還沒有 Threads 帳號。</p> : null}
          </div>
        </Card>

        <Card title="能力檢查">
          <div className="page-grid">
            <ReadyRow label="探索" ready={caps?.discover_ready} hint={caps?.discover_hint} />
            <ReadyRow label="AI" ready={caps?.ai_ready} hint={caps?.ai_hint} />
            <ReadyRow label="發文" ready={caps?.publish_ready} hint={caps?.publish_hint} />
            <Badge variant={oauthEnabled ? "success" : "warning"}>{oauthEnabled ? "OAuth 已設定" : "OAuth 尚未設定"}</Badge>
            {guard ? (
              <div className="button-row">
                <Badge variant={guard.paused ? "warning" : "success"}>{guard.paused ? "發文暫停" : "護欄正常"}</Badge>
                {guard.paused ? <Button variant="soft" onClick={() => void resumeGuard()}>解除暫停</Button> : null}
              </div>
            ) : null}
          </div>
        </Card>
      </div>

      <div className="grid-2">
        <Card title="OAuth / API 連線">
          <div className="page-grid">
            <p className="muted">使用 Meta Threads API 發文與讀成效，避免模擬登入風險。建立新帳號後會自動導向 Meta 授權（需後端已設定 OAuth）。</p>
            {!oauthEnabled ? (
              <p className="muted hx-text-sm" style={{ margin: 0 }}>
                OAuth 尚未設定：請在 <code>deploy/.env.dev</code>（或正式環境變數）填入 THREADS_APP_ID、THREADS_APP_SECRET、THREADS_REDIRECT_URI；
                本機 callback 需 ngrok https，並設定 THREADS_OAUTH_SUCCESS_REDIRECT 指回巡樓（例如 <code>https://threads-tool.30cm.net/#accounts</code>）。
              </p>
            ) : oauthRequiresHttps ? (
              <p className="muted hx-text-sm" style={{ margin: 0 }}>Redirect URI 必須是 https（Meta 會拒絕 http callback）。</p>
            ) : null}
            <div className="button-row">
              <Button variant="primary" disabled={!activeId || !oauthEnabled} onClick={() => void startOauth()}>開始 OAuth</Button>
              <Button disabled={!activeId} onClick={() => void smokeTest()}>執行 API smoke test</Button>
            </div>
          </div>
        </Card>

        <Card title="海巡與發文偏好">
          {connection ? (
            <div className="page-grid">
              <p className="muted hx-text-sm" style={{ margin: 0 }}>
                正式海巡、擴圖、主文與獲客留言一律走 Threads API；只有設定頁開啟的「測試海巡」會用 Chrome 爬蟲。
              </p>
              <TogglePref label="海巡結果抓留言（Threads API）" prefs={connection.prefs} keyName="scrape_replies" onChange={(prefs) => setConnection({ ...connection, prefs })} />
              <Button variant="primary" onClick={() => void saveConnection()}>儲存偏好</Button>
            </div>
          ) : (
            <p className="muted">請先選擇帳號。</p>
          )}
        </Card>
      </div>

      {devModeEnabled && activeId && connection ? (
        <DevToolsPanel
          accountId={activeId}
          connection={connection}
          onConnectionChange={setConnection}
          onMessage={setMessage}
          onError={(msg) => setError(new Error(msg))}
        />
      ) : null}

      <Card title="OAuth / API 診斷">
        {diagnostics ? (
          <div className="page-grid">
            <div className="button-row">
              <Badge variant={diagnostics.api_connected ? "success" : "warning"}>{diagnostics.api_connected ? "API 已連線" : "API 未連線"}</Badge>
              <span className="muted">token 到期：{formatNano(diagnostics.token_expires_at)}</span>
            </div>
            <p className="muted">需要 scopes：{diagnostics.scopes.join("、")}</p>
            <div className="table-wrap">
              <table>
                <thead>
                  <tr>
                    <th>項目</th>
                    <th>Scope</th>
                    <th>狀態</th>
                    <th>訊息</th>
                  </tr>
                </thead>
                <tbody>
                  {diagnostics.items.map((item) => (
                    <tr key={`${item.scope}-${item.name}`}>
                      <td>{item.name}</td>
                      <td>{item.scope}</td>
                      <td><Badge variant={item.status === "ok" ? "success" : item.status === "skip" ? "neutral" : "warning"}>{item.status}</Badge></td>
                      <td>{item.message}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        ) : (
          <p className="muted">選擇帳號後會顯示診斷結果。</p>
        )}
      </Card>

      <Card title="AI 設定">
        {aiSettings || activeId ? (
          <div className="grid-2">
            <Field label="文案 provider">
              <Select value={provider} onChange={(e) => setProvider(e.target.value)}>
                <option value="opencode-go">OpenCode Go</option>
                <option value="xai">xAI</option>
              </Select>
            </Field>
            <Field label="文案 model">
              <div className="button-row">
                {modelsByProvider[provider]?.length ? (
                  <Select value={model} onChange={(e) => setModel(e.target.value)}>
                    <option value="">選擇模型</option>
                    {modelsByProvider[provider].map((item) => <option key={item} value={item}>{item}</option>)}
                  </Select>
                ) : (
                  <Input value={model} onChange={(e) => setModel(e.target.value)} placeholder="例如 deepseek-v4-pro" />
                )}
                <Button disabled={!activeId || loadingModels === "copy"} onClick={() => void fetchModels("copy")}>
                  {loadingModels === "copy" ? "讀取中" : "取得模型"}
                </Button>
              </div>
            </Field>
            <Field label="研究 provider">
              <Select value={researchProvider} onChange={(e) => setResearchProvider(e.target.value)}>
                <option value="opencode-go">OpenCode Go</option>
                <option value="xai">xAI</option>
              </Select>
            </Field>
            <Field label="研究 model">
              <div className="button-row">
                {modelsByProvider[researchProvider]?.length ? (
                  <Select value={researchModel} onChange={(e) => setResearchModel(e.target.value)}>
                    <option value="">選擇模型</option>
                    {modelsByProvider[researchProvider].map((item) => <option key={item} value={item}>{item}</option>)}
                  </Select>
                ) : (
                  <Input value={researchModel} onChange={(e) => setResearchModel(e.target.value)} />
                )}
                <Button disabled={!activeId || loadingModels === "research"} onClick={() => void fetchModels("research")}>
                  {loadingModels === "research" ? "讀取中" : "取得模型"}
                </Button>
              </div>
            </Field>
            <Field label="API key">
              <Input type="password" value={apiKey} onChange={(e) => setApiKey(e.target.value)} placeholder="只在儲存時送出，不顯示既有 key" />
            </Field>
            <div className="button-row" style={{ alignSelf: "end" }}>
              <Button variant="primary" onClick={() => void saveAi()}>儲存 AI 設定</Button>
            </div>
          </div>
        ) : (
          <p className="muted">請先建立帳號。</p>
        )}
      </Card>
    </div>
  );
}

function ReadyRow({ label, ready, hint }: { label: string; ready?: boolean; hint?: string }) {
  return (
    <div className="button-row" style={{ justifyContent: "space-between" }}>
      <span>{label}</span>
      <Badge variant={ready ? "success" : "warning"}>{ready ? "Ready" : hint || "未完成"}</Badge>
    </div>
  );
}

function TogglePref({
  label,
  prefs,
  keyName,
  onChange
}: {
  label: string;
  prefs: Record<string, unknown>;
  keyName: string;
  onChange: (prefs: Record<string, unknown>) => void;
}) {
  return (
    <label className="button-row" style={{ justifyContent: "space-between" }}>
      <span>{label}</span>
      <input type="checkbox" checked={Boolean(prefs[keyName])} onChange={(e) => onChange({ ...prefs, [keyName]: e.target.checked })} />
    </label>
  );
}
