"use client";

/**
 * PairView — 配對頁（AF4 實作）
 *
 * 對齊 spec §5：
 *   - 標題 + description
 *   - Token 輸入卡（使用抽出的 TokenInput 元件：格式驗證 + trim + Enter 送出）
 *   - 輔助連結（到雲端網頁產生）— Phase 0 URL 寫死 placeholder（spec §5.2 C 明列）
 *   - 按鈕列（取消 / 配對，含 loading state）
 *   - Alert 底部提示（Token 15 分鐘有效）
 *   - 錯誤訊息對照（7 種，對應 PairErrorCode）
 *   - 成功 → 0.5s 後自動切到狀態頁 + toast「配對成功」（D2 決議，spec §5.3）
 *
 * 資料來源：
 *   - usePair() → pair(token) Promise; submitting; lastError; reset()
 */

import { useEffect, useRef, useState } from "react";
import { ArrowUpRight } from "lucide-react";
import { toast } from "sonner";

import { TokenInput, validateToken } from "@/components/agent/token-input";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Spinner } from "@/components/ui/spinner";
import { usePair } from "@/hooks/use-pair";
import { agentAPI } from "@/lib/agent-api";
import { useT } from "@/lib/i18n/context";
import type { PairError, PairErrorCode } from "@/types/agent";

import { AGENT_SWITCH_TAB_EVENT } from "./status-view";

/** 雲端產生 token 的 URL（Phase 0 placeholder；正式上線改為環境變數驅動）。 */
const CLOUD_PAIR_URL = "https://visionA.cloud/devices/pair";

/** 成功後切回狀態頁的延遲（spec §5.3「0.5 秒後自動切回」）。 */
const PAIR_SUCCESS_REDIRECT_MS = 500;

/** PairErrorCode → i18n key 對照（spec §5.4）。 */
const ERROR_I18N_KEY: Record<PairErrorCode, string> = {
  token_expired: "pair.error.tokenExpired",
  token_used: "pair.error.tokenUsed",
  token_invalid: "pair.error.tokenInvalid",
  token_revoked: "pair.error.tokenRevoked",
  network_error: "pair.error.network",
  relay_unreachable: "pair.error.relayUnreachable",
  unknown: "pair.error.unknown",
};

/** 切回狀態頁（透過 StatusView 定義的 CustomEvent）。 */
function goBackToStatus() {
  if (typeof window === "undefined") return;
  window.dispatchEvent(
    new CustomEvent<{ value: string }>(AGENT_SWITCH_TAB_EVENT, {
      detail: { value: "status" },
    }),
  );
}

export function PairView() {
  const t = useT();
  const { pair, submitting, lastError, reset } = usePair();
  const [token, setToken] = useState("");

  const validity = validateToken(token);
  const canSubmit = validity === "valid" && !submitting;

  /**
   * spec §5.5 / Fix-F2：Esc 鍵 cancel → 切回狀態頁。
   *
   * - 用 ref 把 submitting 的最新值保留給 listener（避免 stale closure 重綁 listener）
   * - submitting=true 時 Esc 不動（避免使用者誤操作打斷送出中的請求）
   * - mount 才綁、unmount 解綁，避免 memory leak / 跨 view 殘留
   * - 雛形階段不做「未儲存提示」確認對話（spec 沒要求）
   */
  const submittingRef = useRef(submitting);
  useEffect(() => {
    submittingRef.current = submitting;
  }, [submitting]);

  useEffect(() => {
    function onKeyDown(e: KeyboardEvent) {
      if (e.key !== "Escape") return;
      if (submittingRef.current) return;
      e.preventDefault();
      // 不呼叫 handleCancel（會碰到 stale closure 的 reset/setToken；
      // 這裡直接切 tab 即可，token state 隨 unmount 一起釋放）
      goBackToStatus();
    }
    window.addEventListener("keydown", onKeyDown);
    return () => window.removeEventListener("keydown", onKeyDown);
  }, []);

  /** 將 PairError 轉為使用者可見的字串（處理變數內插）。 */
  function formatError(err: PairError): string {
    const raw = t(ERROR_I18N_KEY[err.code]);
    if (err.code === "relay_unreachable" && err.relayUrl) {
      return raw.replace("{url}", err.relayUrl);
    }
    return raw;
  }

  async function handleSubmit() {
    if (!canSubmit) return;
    try {
      await pair(token);
      toast.success(t("pair.success"));
      // D2 決議：0.5 秒後自動切回狀態頁
      window.setTimeout(goBackToStatus, PAIR_SUCCESS_REDIRECT_MS);
    } catch {
      // lastError 會由 hook 自動設定；此處不做額外處理
      // （toast 不顯示；錯誤由頁內 Alert 呈現，避免雙重通知）
    }
  }

  function handleCancel() {
    setToken("");
    reset();
    goBackToStatus();
  }

  function handleChange(next: string) {
    setToken(next);
    // 使用者修改 token → 清掉上次錯誤（避免舊錯誤誤導）
    if (lastError) reset();
  }

  function handleOpenCloud() {
    // Fix-F3：統一走 agentAPI.openURL；Wails runtime 會用 BrowserOpenURL，
    // mock 環境 fallback 到 window.open
    agentAPI.openURL(CLOUD_PAIR_URL);
  }

  return (
    <section
      data-testid="pair-view"
      aria-labelledby="pair-view-heading"
      className="flex flex-col gap-6 py-4"
    >
      {/* 標題區（spec §5.2 A） */}
      <div className="space-y-1 text-center">
        <h2
          id="pair-view-heading"
          className="text-2xl font-semibold"
        >
          {t("pair.title")}
        </h2>
        <p className="text-muted-foreground text-sm">{t("pair.description")}</p>
      </div>

      {/* Token 輸入卡（spec §5.2 B-D） */}
      <Card>
        <CardContent className="space-y-4">
          <TokenInput
            value={token}
            onChange={handleChange}
            onSubmit={handleSubmit}
            disabled={submitting}
            autoFocus
          />

          {/* 錯誤訊息（僅在配對失敗時顯示） */}
          {lastError && (
            <Alert variant="destructive" data-testid="pair-error">
              <AlertDescription>{formatError(lastError)}</AlertDescription>
            </Alert>
          )}

          {/* 輔助連結（spec §5.2 C） */}
          <div className="flex items-center justify-between gap-3">
            <Button
              type="button"
              variant="link"
              size="sm"
              className="h-auto p-0 text-xs"
              onClick={handleOpenCloud}
              data-testid="pair-link-cloud"
            >
              {t("pair.linkCloud")}
              <ArrowUpRight aria-hidden="true" className="ml-0.5 size-3" />
            </Button>

            {/* 按鈕列 — 取消 / 配對 */}
            <div className="flex items-center gap-2">
              <Button
                type="button"
                variant="ghost"
                onClick={handleCancel}
                disabled={submitting}
                data-testid="pair-button-cancel"
              >
                {t("pair.button.cancel")}
              </Button>
              <Button
                type="button"
                variant="default"
                onClick={handleSubmit}
                disabled={!canSubmit}
                aria-busy={submitting}
                data-testid="pair-button-submit"
              >
                {submitting ? (
                  <>
                    <Spinner size="sm" label={t("pair.button.submitting")} />
                    <span>{t("pair.button.submitting")}</span>
                  </>
                ) : (
                  t("pair.button.submit")
                )}
              </Button>
            </div>
          </div>
        </CardContent>
      </Card>

      {/* 底部安全提示（spec §5.2 E） */}
      <Alert variant="info" data-testid="pair-alert-security">
        <AlertDescription>{t("pair.alert.security")}</AlertDescription>
      </Alert>
    </section>
  );
}
