import { useEffect, useState, useTransition } from "react";
import { useShallow } from "zustand/react/shallow";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import { useKisRuntimeStore } from "@/features/settings/store/use-kis-runtime-store";
import {
  revokeKisCredentials,
  validateKisCredentials,
} from "@/features/settings/apis/kis-auth.api";
import {
  getRememberedKisValue,
  isKisRememberEnabled,
  setKisRememberEnabled,
  setRememberedKisValue,
} from "@/features/settings/lib/kis-remember-storage";
import {
  KeyRound,
  ShieldCheck,
  CheckCircle2,
  XCircle,
  Lock,
  Link2,
  Unlink2,
  Activity,
  Zap,
  KeySquare,
} from "lucide-react";
import type { LucideIcon } from "lucide-react";
import { InlineSpinner } from "@/components/ui/loading-spinner";
import { SettingsCard } from "./SettingsCard";

/**
 * @description 한국투자증권 앱키/앱시크릿키 인증 폼입니다.
 * @remarks UI 흐름: /settings -> 앱키/앱시크릿키 입력 -> 연결 확인 버튼 -> /api/kis/validate -> 연결 상태 반영
 * @see app/api/kis/validate/route.ts 앱키 검증 API
 * @see features/settings/store/use-kis-runtime-store.ts 인증 상태 저장소
 */
export function KisAuthForm() {
  const {
    kisTradingEnvInput,
    kisAppKeyInput,
    kisAppSecretInput,
    verifiedAccountNo,
    hasHydrated,
    verifiedCredentials,
    isKisVerified,
    setKisTradingEnvInput,
    setKisAppKeyInput,
    setKisAppSecretInput,
    setVerifiedKisSession,
    invalidateKisVerification,
    clearKisRuntimeSession,
  } = useKisRuntimeStore(
    useShallow((state) => ({
      kisTradingEnvInput: state.kisTradingEnvInput,
      kisAppKeyInput: state.kisAppKeyInput,
      kisAppSecretInput: state.kisAppSecretInput,
      verifiedAccountNo: state.verifiedAccountNo,
      hasHydrated: state._hasHydrated,
      verifiedCredentials: state.verifiedCredentials,
      isKisVerified: state.isKisVerified,
      setKisTradingEnvInput: state.setKisTradingEnvInput,
      setKisAppKeyInput: state.setKisAppKeyInput,
      setKisAppSecretInput: state.setKisAppSecretInput,
      setVerifiedKisSession: state.setVerifiedKisSession,
      invalidateKisVerification: state.invalidateKisVerification,
      clearKisRuntimeSession: state.clearKisRuntimeSession,
    })),
  );

  const [statusMessage, setStatusMessage] = useState<string | null>(null);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [isValidating, startValidateTransition] = useTransition();
  const [isRevoking, startRevokeTransition] = useTransition();
  // [State] 앱키 입력값을 브라우저 재접속 후 자동 복원할지 여부
  const [rememberAppKey, setRememberAppKey] = useState(() =>
    isKisRememberEnabled("appKey"),
  );
  // [State] 앱시크릿키 입력값을 브라우저 재접속 후 자동 복원할지 여부
  const [rememberAppSecret, setRememberAppSecret] = useState(() =>
    isKisRememberEnabled("appSecret"),
  );

  useEffect(() => {
    if (!hasHydrated || kisAppKeyInput.trim()) {
      return;
    }

    // [Step 1] 세션 입력값이 비어 있을 때만 저장된 앱키를 복원합니다.
    const rememberedAppKey = getRememberedKisValue("appKey");
    if (rememberedAppKey) {
      setKisAppKeyInput(rememberedAppKey);
    }
  }, [hasHydrated, kisAppKeyInput, setKisAppKeyInput]);

  useEffect(() => {
    if (!hasHydrated || kisAppSecretInput.trim()) {
      return;
    }

    // [Step 1] 세션 입력값이 비어 있을 때만 저장된 앱시크릿키를 복원합니다.
    const rememberedAppSecret = getRememberedKisValue("appSecret");
    if (rememberedAppSecret) {
      setKisAppSecretInput(rememberedAppSecret);
    }
  }, [hasHydrated, kisAppSecretInput, setKisAppSecretInput]);

  useEffect(() => {
    if (!hasHydrated) {
      return;
    }

    // [Step 2] 앱키 기억하기 체크 상태를 저장/해제합니다.
    setKisRememberEnabled("appKey", rememberAppKey);
  }, [hasHydrated, rememberAppKey]);

  useEffect(() => {
    if (!hasHydrated || !rememberAppKey) {
      return;
    }

    // [Step 2] 앱키 입력값이 바뀔 때 기억하기가 켜져 있으면 값을 갱신합니다.
    setRememberedKisValue("appKey", kisAppKeyInput);
  }, [hasHydrated, rememberAppKey, kisAppKeyInput]);

  useEffect(() => {
    if (!hasHydrated) {
      return;
    }

    // [Step 2] 앱시크릿키 기억하기 체크 상태를 저장/해제합니다.
    setKisRememberEnabled("appSecret", rememberAppSecret);
  }, [hasHydrated, rememberAppSecret]);

  useEffect(() => {
    if (!hasHydrated || !rememberAppSecret) {
      return;
    }

    // [Step 2] 앱시크릿키 입력값이 바뀔 때 기억하기가 켜져 있으면 값을 갱신합니다.
    setRememberedKisValue("appSecret", kisAppSecretInput);
  }, [hasHydrated, rememberAppSecret, kisAppSecretInput]);

  function handleValidate() {
    startValidateTransition(async () => {
      try {
        setErrorMessage(null);
        setStatusMessage(null);

        const appKey = kisAppKeyInput.trim();
        const appSecret = kisAppSecretInput.trim();
        if (!appKey || !appSecret) {
          throw new Error("앱키와 앱시크릿키를 모두 입력해 주세요.");
        }

        const credentials = {
          appKey,
          appSecret,
          tradingEnv: kisTradingEnvInput,
          accountNo: verifiedAccountNo ?? "",
        };

        const result = await validateKisCredentials(credentials);
        setVerifiedKisSession(credentials, result.tradingEnv);
        setStatusMessage(
          `${result.message} (${result.tradingEnv === "real" ? "실전" : "모의"})`,
        );
      } catch (err) {
        invalidateKisVerification();
        setErrorMessage(
          err instanceof Error
            ? err.message
            : "앱키 확인 중 오류가 발생했습니다.",
        );
      }
    });
  }

  function handleRevoke() {
    if (!verifiedCredentials) return;

    startRevokeTransition(async () => {
      try {
        setErrorMessage(null);
        setStatusMessage(null);
        const result = await revokeKisCredentials(verifiedCredentials);
        clearKisRuntimeSession(result.tradingEnv);
        setStatusMessage(
          `${result.message} (${result.tradingEnv === "real" ? "실전" : "모의"})`,
        );
      } catch (err) {
        setErrorMessage(
          err instanceof Error
            ? err.message
            : "연결 해제 중 오류가 발생했습니다.",
        );
      }
    });
  }

  return (
    <SettingsCard
      icon={KeyRound}
      title="한국투자증권 앱키 연결"
      description="Open API에서 발급받은 앱키와 앱시크릿키를 입력해 연결을 완료하세요."
      badge={
        isKisVerified ? (
          <span className="inline-flex shrink-0 items-center gap-1 whitespace-nowrap rounded-full bg-green-50 px-2 py-0.5 text-[11px] font-medium text-green-700 ring-1 ring-green-600/20 dark:bg-green-500/10 dark:text-green-400 dark:ring-green-500/30">
            <CheckCircle2 className="h-3 w-3" />
            연결됨
          </span>
        ) : undefined
      }
      footer={{
        actions: (
          <div className="flex flex-wrap gap-2">
            <Button
              onClick={handleValidate}
              disabled={
                isValidating ||
                !kisAppKeyInput.trim() ||
                !kisAppSecretInput.trim()
              }
              className="h-9 rounded-lg bg-brand-600 px-4 text-xs font-semibold text-white shadow-sm transition-all hover:bg-brand-700 hover:shadow disabled:opacity-50 disabled:shadow-none dark:bg-brand-600 dark:hover:bg-brand-500"
            >
              {isValidating ? (
                <span className="flex items-center gap-1.5">
                  <InlineSpinner className="h-3 w-3 text-white" />
                  검증 중
                </span>
              ) : (
                <span className="flex items-center gap-1.5">
                  <Link2 className="h-3.5 w-3.5 text-brand-100" />
                  앱키 연결 확인
                </span>
              )}
            </Button>

            <Button
              variant="outline"
              onClick={handleRevoke}
              disabled={isRevoking || !verifiedCredentials}
              className="h-9 rounded-lg border-zinc-200 bg-white px-4 text-xs text-zinc-600 hover:bg-zinc-50 hover:text-zinc-900 disabled:cursor-not-allowed disabled:opacity-50 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-400 dark:hover:text-zinc-200"
            >
              {isRevoking ? (
                "해제 중"
              ) : (
                <span className="flex items-center gap-1.5">
                  <Unlink2 className="h-3.5 w-3.5" />
                  연결 해제(토큰 폐기)
                </span>
              )}
            </Button>
          </div>
        ),
        status: (
          <div className="flex min-h-5 items-center justify-start sm:justify-end">
            {errorMessage && (
              <p className="animate-in fade-in slide-in-from-right-4 flex items-center gap-1.5 text-xs font-semibold text-red-500">
                <XCircle className="h-3.5 w-3.5" />
                {errorMessage}
              </p>
            )}
            {statusMessage && (
              <p className="animate-in fade-in slide-in-from-right-4 flex items-center gap-1.5 text-xs font-semibold text-brand-600 dark:text-brand-400">
                <CheckCircle2 className="h-3.5 w-3.5" />
                {statusMessage}
              </p>
            )}
            {!errorMessage && !statusMessage && !isKisVerified && (
              <p className="flex items-center gap-1.5 text-xs text-zinc-400 dark:text-zinc-600">
                <span className="h-1.5 w-1.5 rounded-full bg-zinc-300 dark:bg-zinc-700" />
                미연결 상태입니다
              </p>
            )}
          </div>
        ),
      }}
      className="h-full"
    >
      <div className="space-y-4">
        {/* ========== TRADING MODE ========== */}
        <section className="rounded-xl border border-zinc-200 bg-zinc-50/70 p-3 dark:border-zinc-800 dark:bg-zinc-900/30">
          <div className="mb-2 flex items-center gap-1.5 text-xs font-semibold text-zinc-700 dark:text-zinc-200">
            <ShieldCheck className="h-3.5 w-3.5 text-brand-500" />
            투자 모드 선택
          </div>
          <div className="grid grid-cols-2 gap-2">
            <button
              type="button"
              onClick={() => setKisTradingEnvInput("real")}
              className={cn(
                "flex h-9 items-center justify-center gap-1.5 rounded-lg border text-xs font-semibold transition",
                kisTradingEnvInput === "real"
                  ? "border-brand-500 bg-brand-600 text-white shadow-sm"
                  : "border-zinc-200 bg-white text-zinc-600 hover:border-zinc-300 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300",
              )}
            >
              <Zap className="h-3.5 w-3.5" />
              실전 투자
            </button>
            <button
              type="button"
              onClick={() => setKisTradingEnvInput("mock")}
              className={cn(
                "flex h-9 items-center justify-center gap-1.5 rounded-lg border text-xs font-semibold transition",
                kisTradingEnvInput === "mock"
                  ? "border-zinc-700 bg-zinc-800 text-white shadow-sm dark:border-zinc-500 dark:bg-zinc-700"
                  : "border-zinc-200 bg-white text-zinc-600 hover:border-zinc-300 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300",
              )}
            >
              <Activity className="h-3.5 w-3.5" />
              모의 투자
            </button>
          </div>
        </section>

        {/* ========== APP KEY INPUTS ========== */}
        <div className="space-y-3">
          <div className="space-y-2">
            <CredentialInput
              id="kis-app-key"
              label="앱키"
              placeholder="한국투자증권 앱키 입력"
              value={kisAppKeyInput}
              onChange={setKisAppKeyInput}
              icon={KeySquare}
            />
            <RememberCheckbox
              id="remember-kis-app-key"
              checked={rememberAppKey}
              onChange={setRememberAppKey}
              label="앱키 기억하기"
            />
          </div>

          <div className="space-y-2">
            <CredentialInput
              id="kis-app-secret"
              label="앱시크릿키"
              placeholder="한국투자증권 앱시크릿키 입력"
              value={kisAppSecretInput}
              onChange={setKisAppSecretInput}
              icon={Lock}
            />
            <RememberCheckbox
              id="remember-kis-app-secret"
              checked={rememberAppSecret}
              onChange={setRememberAppSecret}
              label="앱시크릿키 기억하기"
            />
          </div>
        </div>
      </div>
    </SettingsCard>
  );
}

/**
 * @description 앱키/시크릿키 입력 전용 필드 블록입니다.
 * @see features/settings/components/KisAuthForm.tsx 입력 UI 렌더링
 */
function CredentialInput({
  id,
  label,
  value,
  placeholder,
  onChange,
  icon: Icon,
}: {
  id: string;
  label: string;
  value: string;
  placeholder: string;
  onChange: (value: string) => void;
  icon: LucideIcon;
}) {
  return (
    <div className="space-y-1.5">
      <Label htmlFor={id} className="text-xs font-semibold text-zinc-600">
        {label}
      </Label>
      <div className="group/input flex items-center overflow-hidden rounded-xl border border-zinc-200 bg-white transition-colors focus-within:border-brand-500 focus-within:ring-1 focus-within:ring-brand-500 dark:border-zinc-700 dark:bg-zinc-900/20">
        <div className="flex h-10 w-10 shrink-0 items-center justify-center border-r border-zinc-100 bg-zinc-50 text-zinc-400 group-focus-within/input:text-brand-500 dark:border-zinc-800 dark:bg-zinc-800/40">
          <Icon className="h-4 w-4" />
        </div>
        <Input
          id={id}
          type="password"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          placeholder={placeholder}
          className="h-10 border-none bg-transparent px-3 text-sm shadow-none focus-visible:ring-0"
          autoComplete="off"
        />
      </div>
    </div>
  );
}

function RememberCheckbox({
  id,
  checked,
  onChange,
  label,
}: {
  id: string;
  checked: boolean;
  onChange: (checked: boolean) => void;
  label: string;
}) {
  return (
    <div className="flex items-center gap-2 pl-1">
      <Checkbox
        id={id}
        checked={checked}
        onCheckedChange={(next) => onChange(next === true)}
      />
      <Label
        htmlFor={id}
        className="cursor-pointer text-xs font-medium text-zinc-500 dark:text-zinc-300"
      >
        {label}
      </Label>
    </div>
  );
}
