"use client";

/**
 * [파일 역할]
 * 자동매매 제어 패널 UI를 렌더링합니다.
 *
 * [주요 책임]
 * - 프롬프트/기법/리스크 입력값을 받습니다.
 * - 시작/중지/검증 버튼 이벤트를 엔진 훅으로 전달합니다.
 * - 엔진 상태(RUNNING/STOPPING/최근 신호/로그)를 시각적으로 표시합니다.
 */

import { useEffect, useState } from "react";
import { X } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { useAutotradeEngine } from "@/features/autotrade/hooks/useAutotradeEngine";
import { AutotradeWarningBanner } from "@/features/autotrade/components/AutotradeWarningBanner";
import {
  AUTOTRADE_AI_MODE_OPTIONS,
  AUTOTRADE_SUBSCRIPTION_CLI_MODEL_OPTIONS,
  AUTOTRADE_SUBSCRIPTION_CLI_VENDOR_OPTIONS,
  AUTOTRADE_TECHNIQUE_OPTIONS,
} from "@/features/autotrade/types/autotrade.types";
import type { AutotradeRuntimeLog } from "@/features/autotrade/types/autotrade.types";
import type { KisRuntimeCredentials } from "@/features/settings/store/use-kis-runtime-store";
import type {
  DashboardRealtimeTradeTick,
  DashboardStockItem,
} from "@/features/trade/types/trade.types";
import { cn } from "@/lib/utils";

interface AutotradeControlPanelProps {
  selectedStock: DashboardStockItem | null;
  latestTick: DashboardRealtimeTradeTick | null;
  credentials: KisRuntimeCredentials | null;
  canTrade: boolean;
}

export function AutotradeControlPanel({
  selectedStock,
  latestTick,
  credentials,
  canTrade,
}: AutotradeControlPanelProps) {
  /**
   * [데이터 흐름]
   * 설정 UI(프롬프트/기법/리스크) -> useAutotradeEngine 훅 액션 호출 ->
   * /api/autotrade/strategies/compile, /signals/generate ->
   * OpenAI or 구독형 CLI or fallback -> 신호/주문 반영
   */
  // 화면 입력값과 런타임 상태는 엔진 훅에서 중앙 관리합니다.
  const {
    panelOpen,
    setupForm,
    engineState,
    isWorking,
    compiledStrategy,
    validation,
    lastSignal,
    orderCountToday,
    logs,
    setPanelOpen,
    patchSetupForm,
    setNumberField,
    toggleTechnique,
    previewValidation,
    startAutotrade,
    stopAutotrade,
  } = useAutotradeEngine({
    selectedStock,
    latestTick,
    credentials,
    canTrade,
  });

  // [State] 자동매매 실행 중 여부 (배너, 시작/중지 버튼 분기)
  const isRunning = engineState === "RUNNING";
  // [State] 중지 요청 처리 중 여부 (중복 중지 클릭 방지)
  const isStopping = engineState === "STOPPING";
  // [State] 시작 버튼 활성 조건 (인증/동의/작업 중 여부)
  const canStartAutotrade =
    canTrade &&
    !isWorking &&
    setupForm.agreeStopOnExit;
  const shouldShowSubscriptionCliConfig =
    setupForm.aiMode === "subscription_cli" || setupForm.aiMode === "auto";
  const selectedCliModelOptions =
    setupForm.subscriptionCliVendor === "codex"
      ? AUTOTRADE_SUBSCRIPTION_CLI_MODEL_OPTIONS.codex
      : setupForm.subscriptionCliVendor === "gemini"
        ? AUTOTRADE_SUBSCRIPTION_CLI_MODEL_OPTIONS.gemini
        : [];
  const normalizedSubscriptionCliModel = setupForm.subscriptionCliModel.trim();
  const hasPresetModel = selectedCliModelOptions.some(
    (option) => option.value === normalizedSubscriptionCliModel,
  );
  const selectedCliModelSelectValue =
    setupForm.subscriptionCliVendor === "auto"
      ? "__auto__"
      : !normalizedSubscriptionCliModel
        ? "__default__"
        : hasPresetModel
          ? normalizedSubscriptionCliModel
          : "__custom__";
  const [setupTab, setSetupTab] = useState<"quick" | "ai" | "technique">("quick");
  const [isLogPanelOpen, setIsLogPanelOpen] = useState(false);
  const [showTechnicalLog, setShowTechnicalLog] = useState(false);
  const latestSignalRequestLog = logs.find((log) => log.stage === "signal_request") ?? null;
  const latestSignalResponseLog = logs.find((log) => log.stage === "signal_response") ?? null;
  const latestSignalRequestDetail = parseLogDetail(latestSignalRequestLog?.detail);
  const latestSignalResponseDetail = parseLogDetail(latestSignalResponseLog?.detail);
  const latestSignalRequestId =
    latestSignalRequestDetail && typeof latestSignalRequestDetail.requestId === "string"
      ? latestSignalRequestDetail.requestId
      : null;
  const latestSignalResponseId =
    latestSignalResponseDetail && typeof latestSignalResponseDetail.requestId === "string"
      ? latestSignalResponseDetail.requestId
      : null;
  const isSignalResponsePending =
    !!latestSignalRequestId &&
    (!!latestSignalRequestLog &&
      (!latestSignalResponseLog || latestSignalRequestId !== latestSignalResponseId));

  const latestCompletedSignalResponseLog = latestSignalResponseLog;
  const latestCompletedSignalResponseDetail = parseLogDetail(
    latestCompletedSignalResponseLog?.detail,
  );
  const latestCompletedRequestId =
    latestCompletedSignalResponseDetail &&
    typeof latestCompletedSignalResponseDetail.requestId === "string"
      ? latestCompletedSignalResponseDetail.requestId
      : null;
  const latestCompletedSignalRequestLog = latestCompletedRequestId
    ? logs.find((log) => {
        if (log.stage !== "signal_request") return false;
        const detail = parseLogDetail(log.detail);
        return detail?.requestId === latestCompletedRequestId;
      }) ?? null
    : null;
  const latestCompletedSignalRequestDetail = parseLogDetail(
    latestCompletedSignalRequestLog?.detail,
  );

  const latestPromptText =
    (latestCompletedSignalRequestDetail &&
      typeof latestCompletedSignalRequestDetail.promptExcerpt === "string" &&
      latestCompletedSignalRequestDetail.promptExcerpt.trim().length > 0 &&
      latestCompletedSignalRequestDetail.promptExcerpt.trim()) ||
    (latestSignalRequestDetail &&
      typeof latestSignalRequestDetail.promptExcerpt === "string" &&
      latestSignalRequestDetail.promptExcerpt.trim().length > 0 &&
      latestSignalRequestDetail.promptExcerpt.trim()) ||
    setupForm.prompt.trim() ||
    "프롬프트 미입력";

  const latestRequestDataText =
    (latestCompletedSignalRequestDetail &&
      typeof latestCompletedSignalRequestDetail.snapshotSummary === "string" &&
      latestCompletedSignalRequestDetail.snapshotSummary.trim().length > 0 &&
      latestCompletedSignalRequestDetail.snapshotSummary.trim()) ||
    (latestSignalRequestDetail &&
      typeof latestSignalRequestDetail.snapshotSummary === "string" &&
      latestSignalRequestDetail.snapshotSummary.trim().length > 0 &&
      latestSignalRequestDetail.snapshotSummary.trim()) ||
    null;

  const latestAiReasonText =
    (latestCompletedSignalResponseDetail &&
      typeof latestCompletedSignalResponseDetail.reason === "string" &&
      latestCompletedSignalResponseDetail.reason.trim().length > 0 &&
      latestCompletedSignalResponseDetail.reason.trim()) ||
    null;
  const allocationPercentPresets = [5, 10, 15, 20, 30] as const;
  const allocationReferenceCash = validation?.cashBalance ?? 0;
  const allocationByPercentAmount =
    allocationReferenceCash > 0
      ? Math.floor((allocationReferenceCash * Math.max(0, setupForm.allocationPercent)) / 100)
      : 0;
  const estimatedBuyableQuantityByCurrentPrice =
    validation && latestTick?.price && latestTick.price > 0
      ? Math.max(0, Math.floor(validation.effectiveAllocationAmount / latestTick.price))
      : 0;
  const budgetCardValue = validation
    ? `${validation.effectiveAllocationAmount.toLocaleString("ko-KR")}원`
    : `${setupForm.allocationAmount.toLocaleString("ko-KR")}원 (입력 기준)`;

  useEffect(() => {
    if (setupForm.subscriptionCliVendor === "auto") return;
    if (setupForm.subscriptionCliModel.trim().length > 0) return;

    patchSetupForm({
      subscriptionCliModel:
        setupForm.subscriptionCliVendor === "codex" ? "gpt-5.4" : "auto",
    });
  }, [
    patchSetupForm,
    setupForm.subscriptionCliModel,
    setupForm.subscriptionCliVendor,
  ]);

  const handleOpenPanel = () => {
    // [Step 1] 설정 모달을 열어 사용자 입력을 받습니다.
    setSetupTab("quick");
    setPanelOpen(true);
  };

  const handleClosePanel = () => {
    // [Step 1] 설정 모달을 닫고 현재 입력값은 store에 유지합니다.
    setPanelOpen(false);
  };

  const handleEmergencyStop = () => {
    // [Step 1] 경고 배너에서 긴급 중지를 요청합니다.
    // [Step 2] 엔진 훅이 stop API와 상태 정리를 수행합니다.
    void stopAutotrade("emergency");
  };

  const handleStartAutotrade = () => {
    // [Step 1] 엔진 훅의 시작 플로우(compile -> validate -> session start)를 실행합니다.
    void startAutotrade();
  };

  const handleManualStop = () => {
    // [Step 1] 사용자가 수동 중지를 요청합니다.
    // [Step 2] 엔진 훅이 세션 stop API 호출 후 상태를 STOPPED로 전환합니다.
    void stopAutotrade("manual");
  };

  const handlePreviewValidation = () => {
    // [Step 1] compile + validate를 먼저 실행해 실제 적용 투자금/손실한도를 미리 확인합니다.
    void previewValidation();
  };

  const handleAiModeChange = (nextMode: (typeof AUTOTRADE_AI_MODE_OPTIONS)[number]["id"]) => {
    // [Step 1] 선택한 AI 모드를 setupForm에 반영합니다.
    patchSetupForm({ aiMode: nextMode });
  };

  const handlePromptChange = (nextPrompt: string) => {
    // [Step 1] 프롬프트 입력값을 store에 반영합니다.
    // [Step 2] 시작/검증 시 setupForm.prompt가 compile API로 전달됩니다.
    patchSetupForm({ prompt: nextPrompt });
  };

  const handleSubscriptionCliVendorChange = (
    nextVendor: (typeof AUTOTRADE_SUBSCRIPTION_CLI_VENDOR_OPTIONS)[number]["id"],
  ) => {
    // [Step 1] 구독형 CLI 벤더(codex/gemini/auto)를 저장합니다.
    // [Step 2] 벤더 변경 시 기본 모델을 자동 적용해 테스트 입력 단계를 줄입니다.
    const defaultModel =
      nextVendor === "auto"
        ? ""
        : nextVendor === "codex"
          ? "gpt-5.4"
          : "auto";
    patchSetupForm({
      subscriptionCliVendor: nextVendor,
      subscriptionCliModel: defaultModel,
    });
  };

  const handleSubscriptionCliModelSelectChange = (nextValue: string) => {
    if (nextValue === "__default__") {
      patchSetupForm({ subscriptionCliModel: "" });
      return;
    }

    if (nextValue === "__custom__" || nextValue === "__auto__") {
      return;
    }

    patchSetupForm({ subscriptionCliModel: nextValue });
  };

  const handleSubscriptionCliModelInputChange = (nextModel: string) => {
    patchSetupForm({ subscriptionCliModel: nextModel });
  };

  const handleAgreeStopOnExitChange = (nextChecked: boolean | "indeterminate") => {
    // [Step 1] 브라우저 이탈 시 자동중지 동의 값을 저장합니다.
    patchSetupForm({ agreeStopOnExit: nextChecked === true });
  };

  const handleApplyAllocationPercentPreset = (percent: number) => {
    patchSetupForm({ allocationPercent: percent });
  };

  const handleSyncAllocationAmountFromPercent = () => {
    if (allocationByPercentAmount <= 0) return;
    patchSetupForm({ allocationAmount: allocationByPercentAmount });
  };

  const applyPreset = (preset: "starter" | "balanced" | "active") => {
    // [Step 1] 프리셋 종류에 따라 권장 리스크 값을 한번에 채웁니다.
    if (preset === "starter") {
      patchSetupForm({
        allocationPercent: 5,
        allocationAmount: 300000,
        dailyLossPercent: 1.5,
        dailyLossAmount: 25000,
        confidenceThreshold: 0.72,
      });
      return;
    }

    if (preset === "balanced") {
      patchSetupForm({
        allocationPercent: 10,
        allocationAmount: 500000,
        dailyLossPercent: 2,
        dailyLossAmount: 50000,
        confidenceThreshold: 0.67,
      });
      return;
    }

    patchSetupForm({
      allocationPercent: 15,
      allocationAmount: 1000000,
      dailyLossPercent: 3,
      dailyLossAmount: 100000,
      confidenceThreshold: 0.6,
    });
  };

  return (
    <>
      {/* ===== 1. 실행 중 경고 배너 (중지 버튼 포함) ===== */}
      <AutotradeWarningBanner
        visible={isRunning || isStopping}
        isStopping={isStopping}
        onStop={handleEmergencyStop}
      />

      <section className="border-b border-border/70 bg-background/95 px-3 py-2 backdrop-blur-sm dark:border-brand-800/45 dark:bg-brand-900/20 sm:px-4">
        <div className="mx-auto flex w-full max-w-450 flex-col gap-1.5">
          {/* ===== 2. 상단 상태/액션 영역 ===== */}
          <div className="flex flex-wrap items-center gap-2">
            <Badge variant={resolveStatusBadgeVariant(engineState)}>
              자동매매 {engineState}
            </Badge>
            {selectedStock ? (
              <Badge variant="outline">
                대상 종목: {selectedStock.name} ({selectedStock.symbol})
              </Badge>
            ) : (
              <Badge variant="outline">대상 종목 미선택</Badge>
            )}
            <Badge variant="outline">당일 자동주문 {orderCountToday}건</Badge>

            <div className="ml-auto flex items-center gap-2">
              <Button
                type="button"
                variant="outline"
                size="sm"
                onClick={handleOpenPanel}
                disabled={!canTrade}
              >
                자동매매 설정
              </Button>

              {!isRunning ? (
                <Button
                  type="button"
                  size="sm"
                  onClick={handleStartAutotrade}
                  disabled={isWorking || !canTrade}
                >
                  {isWorking ? "시작 준비 중..." : "자동매매 시작"}
                </Button>
              ) : (
                <Button
                  type="button"
                  size="sm"
                  variant="destructive"
                  onClick={handleManualStop}
                  disabled={isStopping}
                >
                  {isStopping ? "중지 중..." : "자동매매 중지"}
                </Button>
              )}
            </div>
          </div>

          {/* ===== 3. 상태 카드 영역 ===== */}
          <div className="grid gap-2 md:grid-cols-2 xl:grid-cols-4">
            <StatusItem
              label="전략 요약"
              value={compiledStrategy?.summary ?? "아직 컴파일된 전략이 없습니다."}
            />
            <StatusItem
              label="오늘 자동매매 예산"
              value={budgetCardValue}
            />
            <StatusItem
              label="오늘 자동중지 손실선"
              value={
                validation
                  ? `${validation.effectiveDailyLossLimit.toLocaleString("ko-KR")}원`
                  : "-"
              }
            />
            <StatusItem
              label="최근 신호"
              value={
                lastSignal
                  ? `${lastSignal.signal.toUpperCase()} (${lastSignal.confidence.toFixed(2)})`
                  : "신호 없음"
              }
              tone={
                lastSignal?.signal === "buy"
                  ? "buy"
                  : lastSignal?.signal === "sell"
                    ? "sell"
                    : "default"
              }
            />
          </div>

          {/* ===== 4. 최근 로그 요약 ===== */}
          {(logs.length > 0 || isRunning || isStopping) && (
            <div className="rounded-md border border-border/70 bg-muted/20 px-3 py-2 text-xs dark:border-brand-800/45 dark:bg-brand-900/24">
              <div className="flex items-center justify-between gap-2">
                <p className="font-semibold text-foreground dark:text-brand-50">
                  실시간 자동매매 안내
                </p>
                <div className="flex items-center gap-1">
                  {isLogPanelOpen && (
                    <Button
                      type="button"
                      size="sm"
                      variant="ghost"
                      className="h-7 px-2 text-[11px]"
                      onClick={() => setShowTechnicalLog((prev) => !prev)}
                    >
                      {showTechnicalLog ? "쉬운 보기" : "개발자 상세"}
                    </Button>
                  )}
                  <Button
                    type="button"
                    size="sm"
                    variant="outline"
                    className="h-7 px-2 text-[11px]"
                    onClick={() => setIsLogPanelOpen((prev) => !prev)}
                  >
                    {isLogPanelOpen ? "접기" : "펼치기"}
                  </Button>
                </div>
              </div>

              <div className="mt-1 rounded bg-background/70 px-2 py-1.5 text-[12px] text-foreground dark:bg-brand-900/35 dark:text-brand-50">
                <p>
                  입력:
                  {" "}
                  {latestPromptText || "아직 AI 요청 전입니다."}
                  {(isRunning || isStopping || isSignalResponsePending) && (
                    <span className="ml-1 inline-block animate-pulse text-primary">▍</span>
                  )}
                </p>
                {latestRequestDataText && (
                  <p className="mt-1 text-muted-foreground dark:text-brand-100/75">
                    요청 데이터:
                    {" "}
                    {latestRequestDataText}
                  </p>
                )}
                <p className="mt-1 text-muted-foreground dark:text-brand-100/75">
                  답변:
                  {" "}
                  {latestAiReasonText ?? "아직 응답이 없습니다."}
                  {isSignalResponsePending && (
                    <span className="ml-1 text-primary">
                      (새 분석 진행 중...)
                    </span>
                  )}
                </p>
              </div>

              {isLogPanelOpen && (
                <ul className="mt-2 max-h-44 space-y-2 overflow-y-auto pr-1">
                  {logs.slice(0, 10).map((log) => {
                    const friendly = toFriendlyLog(log);
                    return (
                      <li
                        key={log.id}
                        className="rounded-md border border-border/60 bg-background/80 px-2 py-1.5 dark:border-brand-800/40 dark:bg-brand-900/24"
                      >
                        <div className="flex flex-wrap items-center gap-1.5 text-[11px]">
                          <span className="text-muted-foreground dark:text-brand-100/75">
                            {new Date(log.createdAt).toLocaleTimeString("ko-KR")}
                          </span>
                          <span
                            className={cn(
                              "rounded px-1.5 py-0.5 font-semibold",
                              resolveLogLevelTone(log.level),
                            )}
                          >
                            {log.level.toUpperCase()}
                          </span>
                          {log.stage && (
                            <span className="rounded bg-muted px-1.5 py-0.5 font-medium text-foreground dark:bg-brand-900/45 dark:text-brand-50">
                              {resolveLogStageLabel(log.stage)}
                            </span>
                          )}
                        </div>

                        <p className="mt-1 text-foreground dark:text-brand-50">
                          {friendly.primary}
                        </p>
                        {friendly.secondary && (
                          <p className="mt-0.5 text-muted-foreground dark:text-brand-100/75">
                            {friendly.secondary}
                          </p>
                        )}

                        {showTechnicalLog && log.detail && (
                          <pre className="mt-1 overflow-x-auto rounded bg-muted/35 p-1.5 text-[11px] leading-relaxed text-foreground dark:bg-brand-900/40 dark:text-brand-50">
                            {log.detail}
                          </pre>
                        )}
                      </li>
                    );
                  })}
                </ul>
              )}
            </div>
          )}
        </div>
      </section>

      {/* ===== 5. 설정 모달 ===== */}
      {panelOpen && (
        <div className="fixed inset-0 z-50 overflow-y-auto bg-black/55 p-3 sm:p-4">
          <div className="relative mx-auto w-full max-w-6xl rounded-2xl border border-border bg-background p-4 shadow-2xl max-h-[92vh] overflow-y-auto dark:border-brand-700/55 dark:bg-brand-950 sm:p-5">
            <button
              type="button"
              className="absolute right-3 top-3 rounded-md p-1 text-muted-foreground hover:bg-muted dark:hover:bg-brand-900/35"
              onClick={handleClosePanel}
              aria-label="자동매매 설정 닫기"
            >
              <X className="h-4 w-4" />
            </button>

            <h2 className="text-lg font-semibold text-foreground dark:text-brand-50">
              자동매매 간편 설정
            </h2>
            <p className="mt-1 text-sm text-muted-foreground dark:text-brand-100/70">
              처음 쓰셔도 쉽게 맞출 수 있게 핵심만 모았습니다.
            </p>

            <div className="mt-3 grid gap-2 sm:grid-cols-3">
              <CompactStepCard
                title="1. 빠른 설정"
                description="투자금/손실 한도부터 입력"
              />
              <CompactStepCard
                title="2. AI 선택"
                description="자동 또는 원하는 모델 고르기"
              />
              <CompactStepCard
                title="3. 기법 선택"
                description="원하는 기법만 체크 후 시작"
              />
            </div>

            <div className="mt-3 flex flex-wrap gap-2">
              <Button
                type="button"
                size="sm"
                variant={setupTab === "quick" ? "default" : "outline"}
                onClick={() => setSetupTab("quick")}
              >
                빠른 설정
              </Button>
              <Button
                type="button"
                size="sm"
                variant={setupTab === "ai" ? "default" : "outline"}
                onClick={() => setSetupTab("ai")}
              >
                AI/모델
              </Button>
              <Button
                type="button"
                size="sm"
                variant={setupTab === "technique" ? "default" : "outline"}
                onClick={() => setSetupTab("technique")}
              >
                매매 기법
              </Button>
            </div>

            <div className="mt-4 grid gap-4 lg:grid-cols-[1.15fr_0.85fr]">
              <div className="space-y-4">
                {/* 좌측: 판단 소스/전략 설정 */}
                {setupTab === "ai" && (
                  <>
                    <FieldLabel label="AI 두뇌 선택" />
                    <FieldHelp text="모르겠으면 자동(권장)으로 두면 됩니다." />
                    <select
                      id="autotrade-ai-mode-select"
                      aria-label="AI 판단 모드"
                      className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring dark:border-brand-700/55 dark:bg-brand-900/22"
                      value={setupForm.aiMode}
                      onChange={(event) =>
                        handleAiModeChange(
                          event.target.value as (typeof AUTOTRADE_AI_MODE_OPTIONS)[number]["id"],
                        )
                      }
                    >
                      {AUTOTRADE_AI_MODE_OPTIONS.map((mode) => (
                        <option key={mode.id} value={mode.id}>
                          {mode.label}
                        </option>
                      ))}
                    </select>
                    <p className="text-xs text-muted-foreground dark:text-brand-100/70">
                      {resolveFriendlyAiModeDescription(setupForm.aiMode)}
                    </p>

                    {shouldShowSubscriptionCliConfig && (
                      <div className="space-y-2 rounded-md border border-border/65 bg-muted/20 px-3 py-2 text-xs dark:border-brand-700/45 dark:bg-brand-900/18">
                        <p className="font-semibold text-foreground dark:text-brand-50">
                          모델 선택
                        </p>
                        <FieldHelp text="모델은 성능과 속도의 균형입니다. 추천 모델부터 시작하세요." />
                        <select
                          aria-label="구독형 CLI 벤더 선택"
                          className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring dark:border-brand-700/55 dark:bg-brand-900/22"
                          value={setupForm.subscriptionCliVendor}
                          onChange={(event) =>
                            handleSubscriptionCliVendorChange(
                              event.target
                                .value as (typeof AUTOTRADE_SUBSCRIPTION_CLI_VENDOR_OPTIONS)[number]["id"],
                            )
                          }
                        >
                          {AUTOTRADE_SUBSCRIPTION_CLI_VENDOR_OPTIONS.map((option) => (
                            <option key={option.id} value={option.id}>
                              {option.label}
                            </option>
                          ))}
                        </select>

                        {setupForm.subscriptionCliVendor === "auto" ? (
                          <p className="text-muted-foreground dark:text-brand-100/70">
                            자동 선택은 Codex를 먼저 시도하고, 안 되면 Gemini를 시도합니다.
                          </p>
                        ) : (
                          <>
                            <select
                              aria-label="구독형 CLI 모델 선택"
                              className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring dark:border-brand-700/55 dark:bg-brand-900/22"
                              value={selectedCliModelSelectValue}
                              onChange={(event) =>
                                handleSubscriptionCliModelSelectChange(event.target.value)
                              }
                            >
                              <option value="__default__">CLI 기본 모델 사용 (추천)</option>
                              {selectedCliModelOptions.map((option) => (
                                <option key={option.value} value={option.value}>
                                  {option.label}
                                </option>
                              ))}
                              <option value="__custom__">직접 입력</option>
                            </select>
                            {(selectedCliModelSelectValue === "__custom__" ||
                              normalizedSubscriptionCliModel.length > 0) && (
                              <Input
                                type="text"
                                aria-label="구독형 CLI 모델 직접 입력"
                                value={setupForm.subscriptionCliModel}
                                onChange={(event) =>
                                  handleSubscriptionCliModelInputChange(event.target.value)
                                }
                                placeholder="예) gpt-5.4, gpt-5.3-codex, gpt-5-codex-mini"
                              />
                            )}
                          </>
                        )}
                      </div>
                    )}
                  </>
                )}

                {setupTab === "quick" && (
                  <>
                    <FieldLabel label="전략 한 줄 요청 (선택)" />
                    <FieldHelp text="비워도 기본 기법으로 동작합니다. 한 줄로 간단히 적어주세요." />
                    {/* [프롬프트 흐름] 1) textarea 입력 -> handlePromptChange -> patchSetupForm(prompt) */}
                    {/* [프롬프트 흐름] 2) 시작/검증 클릭 -> startAutotrade or previewValidation -> prepareStrategy */}
                    {/* [프롬프트 흐름] 3) prepareStrategy -> compileAutotradeStrategy -> /api/autotrade/strategies/compile */}
                    <textarea
                      className="min-h-20 w-full rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring dark:border-brand-700/55 dark:bg-brand-900/22"
                      value={setupForm.prompt}
                      onChange={(event) => handlePromptChange(event.target.value)}
                      placeholder="예) 오전에는 짧게, 오후에는 보수적으로 매매해줘"
                    />
                  </>
                )}

                {setupTab === "ai" && (
                  <div className="rounded-md border border-border/65 bg-muted/20 px-3 py-2 text-xs dark:border-brand-700/45 dark:bg-brand-900/18">
                    <p className="font-semibold text-foreground dark:text-brand-50">
                      AI가 참고하는 데이터
                    </p>
                    <p className="mt-1 text-muted-foreground dark:text-brand-100/75">
                      현재가, 등락률, 고가/저가, 체결강도, 호가 잔량, 스프레드, 최근 체결 흐름을 함께
                      보고 판단합니다.
                    </p>
                  </div>
                )}

                {setupTab === "technique" && (
                  <>
                    <FieldLabel label="매매 기법 선택" />
                    <FieldHelp text="기법을 선택하지 않으면 기본 기법(이평교차, VWAP, 박스권 단타)을 자동 적용합니다." />
                    <div className="grid max-h-[22rem] gap-2 overflow-y-auto pr-1 md:grid-cols-2">
                      {AUTOTRADE_TECHNIQUE_OPTIONS.map((technique) => {
                        const checked = setupForm.selectedTechniques.includes(technique.id);

                        return (
                          <label
                            key={technique.id}
                            className={cn(
                              "flex cursor-pointer items-start gap-3 rounded-md border px-3 py-2",
                              checked
                                ? "border-primary/50 bg-primary/10"
                                : "border-border/65 bg-muted/20 dark:border-brand-700/45 dark:bg-brand-900/18",
                            )}
                          >
                            <Checkbox
                              checked={checked}
                              onCheckedChange={(nextChecked) => {
                                toggleTechnique(technique.id, nextChecked === true);
                              }}
                            />
                            <span className="space-y-0.5">
                              <span className="block text-sm font-semibold text-foreground dark:text-brand-50">
                                {technique.label}
                              </span>
                              <span className="block text-xs text-muted-foreground dark:text-brand-100/70">
                                {technique.description}
                              </span>
                            </span>
                          </label>
                        );
                      })}
                    </div>
                    <p className="text-[11px] text-muted-foreground dark:text-brand-100/70">
                      팁: 처음에는 2~3개만 켜고 시작하는 편이 신호 품질을 맞추기 쉽습니다.
                    </p>
                  </>
                )}
              </div>

              <div className="space-y-4">
                {/* 우측: 리스크/동의/검증 요약 */}
                {setupTab === "quick" && (
                  <>
                    <FieldLabel label="오늘 투자금 (비율 + 금액)" />
                    <FieldHelp text="비율을 먼저 고르고, 금액은 자동입력 버튼으로 맞추면 가장 쉽습니다." />
                    <div className="space-y-2 rounded-md border border-border/65 bg-muted/20 px-3 py-2 dark:border-brand-700/45 dark:bg-brand-900/18">
                      <div className="flex flex-wrap gap-2">
                        {allocationPercentPresets.map((percent) => (
                          <Button
                            key={percent}
                            type="button"
                            size="sm"
                            variant={Math.round(setupForm.allocationPercent) === percent ? "default" : "outline"}
                            className="h-7"
                            onClick={() => handleApplyAllocationPercentPreset(percent)}
                          >
                            {percent}%
                          </Button>
                        ))}
                      </div>
                      <Input
                        type="range"
                        min={1}
                        max={100}
                        step={1}
                        value={Math.max(1, Math.min(100, Math.round(setupForm.allocationPercent)))}
                        onChange={(event) =>
                          setNumberField("allocationPercent", event.target.value)
                        }
                        aria-label="투자 비율 슬라이더"
                      />
                      <div className="grid grid-cols-2 gap-2">
                        <Input
                          type="number"
                          min={0}
                          max={100}
                          step={0.5}
                          value={setupForm.allocationPercent}
                          onChange={(event) =>
                            setNumberField("allocationPercent", event.target.value)
                          }
                          placeholder="투자 비율(%)"
                        />
                        <Input
                          type="number"
                          min={0}
                          step={1000}
                          value={setupForm.allocationAmount}
                          onChange={(event) =>
                            setNumberField("allocationAmount", event.target.value)
                          }
                          placeholder="실제 금액(원)"
                        />
                      </div>
                      <div className="flex flex-wrap items-center justify-between gap-2 text-xs text-muted-foreground dark:text-brand-100/70">
                        <p>
                          현재 기준:
                          {" "}
                          {allocationReferenceCash > 0
                            ? `${setupForm.allocationPercent.toFixed(1)}% ≈ ${allocationByPercentAmount.toLocaleString("ko-KR")}원`
                            : "기준 자금 확인 전"}
                        </p>
                        <Button
                          type="button"
                          size="sm"
                          variant="outline"
                          className="h-7"
                          onClick={handleSyncAllocationAmountFromPercent}
                          disabled={allocationByPercentAmount <= 0}
                        >
                          금액 자동입력
                        </Button>
                      </div>
                    </div>

                    <FieldLabel label="하루 손실 한도 (비율 + 금액)" />
                    <FieldHelp text="손실 한도에 도달하면 자동으로 중지합니다." />
                    <div className="grid grid-cols-2 gap-2">
                      <Input
                        type="number"
                        min={0}
                        step={0.1}
                        value={setupForm.dailyLossPercent}
                        onChange={(event) =>
                          setNumberField("dailyLossPercent", event.target.value)
                        }
                        placeholder="참고 비율(%)"
                      />
                      <Input
                        type="number"
                        min={0}
                        step={1000}
                        value={setupForm.dailyLossAmount}
                        onChange={(event) =>
                          setNumberField("dailyLossAmount", event.target.value)
                        }
                        placeholder="실제 금액(원)"
                      />
                    </div>

                    <FieldLabel label="신뢰도 기준 (0.45~0.95)" />
                    <FieldHelp text="0.65라면 65점 이상 신호만 주문합니다." />
                    <Input
                      type="number"
                      min={0.45}
                      max={0.95}
                      step={0.01}
                      value={setupForm.confidenceThreshold}
                      onChange={(event) =>
                        setNumberField("confidenceThreshold", event.target.value)
                      }
                      placeholder="0.65"
                    />

                    <div className="space-y-2 rounded-md border border-border/65 bg-muted/20 px-3 py-2 text-xs dark:border-brand-700/45 dark:bg-brand-900/18">
                      <p className="font-semibold text-foreground dark:text-brand-50">
                        빠른 추천값
                      </p>
                      <div className="flex flex-wrap gap-2">
                        <Button
                          type="button"
                          size="sm"
                          variant="outline"
                          className="h-7"
                          onClick={() => applyPreset("starter")}
                        >
                          초보 추천
                        </Button>
                        <Button
                          type="button"
                          size="sm"
                          variant="outline"
                          className="h-7"
                          onClick={() => applyPreset("balanced")}
                        >
                          균형형
                        </Button>
                        <Button
                          type="button"
                          size="sm"
                          variant="outline"
                          className="h-7"
                          onClick={() => applyPreset("active")}
                        >
                          공격형
                        </Button>
                      </div>
                    </div>

                    <label className="flex items-center gap-2 rounded-md border border-border/65 bg-muted/20 px-3 py-2 text-sm dark:border-brand-700/45 dark:bg-brand-900/18">
                      <Checkbox
                        checked={setupForm.agreeStopOnExit}
                        onCheckedChange={handleAgreeStopOnExitChange}
                      />
                      <span>
                        창을 닫거나 다른 페이지로 이동하면 자동매매를 즉시 중지하는 데 동의합니다.
                      </span>
                    </label>
                  </>
                )}

                <div className="rounded-md border border-border/65 bg-muted/20 px-3 py-2 text-xs dark:border-brand-700/45 dark:bg-brand-900/18">
                  <p className="font-semibold text-foreground dark:text-brand-50">
                    안전 점검 결과
                  </p>
                  {validation ? (
                    <div className="mt-1 space-y-1 text-muted-foreground dark:text-brand-100/75">
                      <p>주문 기준 자금: {validation.cashBalance.toLocaleString("ko-KR")}원</p>
                      <p>오늘 주문 예산: {validation.effectiveAllocationAmount.toLocaleString("ko-KR")}원</p>
                      <p>
                        현재가 기준 예상 매수 가능:
                        {" "}
                        {latestTick?.price && latestTick.price > 0
                          ? `${estimatedBuyableQuantityByCurrentPrice.toLocaleString("ko-KR")}주 (현재가 ${latestTick.price.toLocaleString("ko-KR")}원)`
                          : "현재가 수신 전"}
                      </p>
                      <p>자동중지 손실선: {validation.effectiveDailyLossLimit.toLocaleString("ko-KR")}원</p>
                      <p>점검 상태: {validation.isValid ? "통과" : "차단"}</p>
                      {!validation.isValid && validation.blockedReasons.length > 0 && (
                        <p className="text-red-500 dark:text-red-400">
                          차단 이유: {validation.blockedReasons[0]}
                        </p>
                      )}
                    </div>
                  ) : (
                    <p className="mt-1 text-muted-foreground dark:text-brand-100/75">
                      아직 점검 전입니다. &quot;검증 미리보기&quot;를 눌러 확인해 주세요.
                    </p>
                  )}
                </div>
              </div>
            </div>

            <div className="mt-5 flex flex-wrap justify-end gap-2">
              <Button
                type="button"
                variant="outline"
                onClick={handleClosePanel}
                disabled={isWorking}
              >
                닫기
              </Button>
              <Button
                type="button"
                variant="outline"
                onClick={handlePreviewValidation}
                disabled={isWorking || !canTrade}
              >
                내 설정 점검
              </Button>
              <Button
                type="button"
                onClick={handleStartAutotrade}
                disabled={!canStartAutotrade}
              >
                {isWorking ? "시작 준비 중..." : "자동매매 시작하기"}
              </Button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

function FieldLabel({ label }: { label: string }) {
  return (
    <p className="text-sm font-semibold text-foreground dark:text-brand-50">{label}</p>
  );
}

function FieldHelp({ text }: { text: string }) {
  return (
    <p className="text-xs text-muted-foreground dark:text-brand-100/70">
      {text}
    </p>
  );
}

function CompactStepCard({
  title,
  description,
}: {
  title: string;
  description: string;
}) {
  return (
    <div className="rounded-md border border-border/65 bg-muted/20 px-3 py-2 text-xs dark:border-brand-800/45 dark:bg-brand-900/24">
      <p className="font-semibold text-foreground dark:text-brand-50">{title}</p>
      <p className="mt-1 text-muted-foreground dark:text-brand-100/70">{description}</p>
    </div>
  );
}

function StatusItem({
  label,
  value,
  tone = "default",
}: {
  label: string;
  value: string;
  tone?: "default" | "buy" | "sell";
}) {
  return (
    <div className="rounded-md border border-border/65 bg-muted/20 px-3 py-2 text-xs dark:border-brand-800/45 dark:bg-brand-900/24">
      <p className="text-muted-foreground dark:text-brand-100/70">{label}</p>
      <p
        className={cn(
          "mt-1 line-clamp-2 font-semibold",
          tone === "buy" && "text-red-500 dark:text-red-400",
          tone === "sell" && "text-blue-600 dark:text-blue-400",
          tone === "default" && "text-foreground dark:text-brand-50",
        )}
      >
        {value}
      </p>
    </div>
  );
}

function resolveLogStageLabel(stage: NonNullable<AutotradeRuntimeLog["stage"]>) {
  switch (stage) {
    case "session":
      return "세션";
    case "strategy_compile":
      return "전략컴파일";
    case "strategy_validate":
      return "리스크검증";
    case "signal_request":
      return "신호요청";
    case "signal_response":
      return "신호응답";
    case "risk_gate":
      return "리스크게이트";
    case "order_execution":
      return "주문실행";
    case "order_blocked":
      return "주문차단";
    case "provider_fallback":
      return "대체처리";
    case "engine_error":
      return "오류";
    default:
      return "기타";
  }
}

function resolveLogLevelTone(level: "info" | "warning" | "error") {
  if (level === "error") {
    return "bg-red-500/15 text-red-600 dark:text-red-300";
  }
  if (level === "warning") {
    return "bg-amber-500/20 text-amber-700 dark:text-amber-200";
  }
  return "bg-emerald-500/15 text-emerald-700 dark:text-emerald-200";
}

function toFriendlyLog(log: AutotradeRuntimeLog) {
  const detail = parseLogDetail(log.detail);

  if (!log.stage) {
    return {
      id: log.id,
      primary: log.message,
      secondary: undefined,
    };
  }

  if (log.stage === "strategy_compile") {
    if (typeof detail?.provider === "string") {
      return {
        id: log.id,
        primary: "AI가 자동매매 전략 구성을 완료했어요.",
        secondary: `엔진: ${toProviderLabel(detail.provider)} · 신뢰도 기준 ${toPercentText(detail.confidenceThreshold)}`,
      };
    }
    return {
      id: log.id,
      primary: "AI에게 전략 생성을 요청했어요.",
      secondary: `기법: ${toTechniqueText(detail?.selectedTechniques)}`,
    };
  }

  if (log.stage === "strategy_validate") {
    if (log.level === "warning") {
      return {
        id: log.id,
        primary: "리스크 검증에서 주의가 필요해요.",
        secondary: extractFirstReason(detail) ?? log.message,
      };
    }
    return {
      id: log.id,
      primary: "리스크 검증을 진행했어요.",
      secondary:
        detail && typeof detail.effectiveAllocationAmount === "number"
          ? `오늘 주문 예산 ${toWon(detail.effectiveAllocationAmount)} · 자동중지 ${toWon(detail.effectiveDailyLossLimit)}`
          : undefined,
    };
  }

  if (log.stage === "signal_request") {
    const snapshot = isRecord(detail?.snapshot) ? detail.snapshot : null;
    const volume = snapshot && isRecord(snapshot.volume) ? snapshot.volume : null;
    const currentPrice =
      snapshot && typeof snapshot.currentPrice === "number"
        ? snapshot.currentPrice
        : undefined;
    const changeRate =
      snapshot && typeof snapshot.changeRate === "number"
        ? snapshot.changeRate
        : undefined;
    const volumeRatio =
      volume && typeof volume.volumeRatio === "number"
        ? volume.volumeRatio
        : undefined;
    return {
      id: log.id,
      primary: "AI 판단을 요청했어요. 지금 시세를 분석 중입니다.",
      secondary:
        currentPrice && Number.isFinite(currentPrice)
          ? `현재가 ${toWon(currentPrice)} · 등락률 ${toSignedPercent(changeRate)} · 거래량비 ${toRatioText(volumeRatio)}`
          : undefined,
    };
  }

  if (log.stage === "signal_response") {
    const signalText =
      detail && typeof detail.signal === "string"
        ? toSignalLabel(detail.signal)
        : "판단 수신";
    const confidenceText =
      detail && typeof detail.confidence === "number"
        ? `${Math.round(detail.confidence * 100)}점`
        : "";
    const reasonText =
      detail && typeof detail.reason === "string" ? detail.reason : log.message;

    return {
      id: log.id,
      primary: `AI 판단 결과: ${signalText}${confidenceText ? ` (${confidenceText})` : ""}`,
      secondary: reasonText,
    };
  }

  if (log.stage === "provider_fallback") {
    return {
      id: log.id,
      primary: "AI 응답이 불안정해서 규칙 기반 판단으로 안전 전환했어요.",
      secondary: typeof detail?.fallbackReasonPreview === "string" ? detail.fallbackReasonPreview : undefined,
    };
  }

  if (log.stage === "risk_gate") {
    return {
      id: log.id,
      primary: "리스크 규칙 때문에 주문을 잠시 보류했어요.",
      secondary: extractFirstReason(detail) ?? log.message,
    };
  }

  if (log.stage === "order_blocked") {
    return {
      id: log.id,
      primary: "주문 조건이 맞지 않아 이번 신호는 실행하지 않았어요.",
      secondary: log.message,
    };
  }

  if (log.stage === "order_execution") {
    if (typeof detail?.executedAt === "string") {
      return {
        id: log.id,
        primary: "자동주문이 실제로 실행됐어요.",
        secondary: `${toSideLabel(detail.side)} ${toQuantityText(detail.quantity)} · 가격 ${toWon(detail.orderPrice)}`,
      };
    }

    return {
      id: log.id,
      primary: "자동주문을 거래소로 전송 중입니다.",
      secondary: `${toSideLabel(detail?.side)} ${toQuantityText(detail?.quantity)} · 가격 ${toWon(detail?.orderPrice)}`,
    };
  }

  if (log.stage === "session") {
    return {
      id: log.id,
      primary: "자동매매 세션 상태가 변경됐어요.",
      secondary: log.message,
    };
  }

  if (log.stage === "engine_error") {
    return {
      id: log.id,
      primary: "오류가 감지되어 안전하게 처리 중입니다.",
      secondary: log.message,
    };
  }

  return {
    id: log.id,
    primary: log.message,
    secondary: undefined,
  };
}

function parseLogDetail(detail: string | undefined): Record<string, unknown> | null {
  if (!detail) {
    return null;
  }
  try {
    const parsed = JSON.parse(detail) as unknown;
    return isRecord(parsed) ? parsed : null;
  } catch {
    return null;
  }
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null;
}

function toProviderLabel(value: unknown) {
  const provider = String(value ?? "");
  if (provider === "openai") return "OpenAI";
  if (provider === "subscription_cli") return "구독형 CLI";
  if (provider === "fallback") return "규칙 기반";
  return provider || "-";
}

function toTechniqueText(value: unknown) {
  if (!Array.isArray(value) || value.length === 0) {
    return "기본 기법 자동 적용";
  }
  return value.map((item) => String(item)).join(", ");
}

function toWon(value: unknown) {
  if (typeof value !== "number" || !Number.isFinite(value)) {
    return "-";
  }
  return `${Math.round(value).toLocaleString("ko-KR")}원`;
}

function toPercentText(value: unknown) {
  if (typeof value !== "number" || !Number.isFinite(value)) {
    return "-";
  }
  return `${Math.round(value * 100)}%`;
}

function toSignedPercent(value: unknown) {
  if (typeof value !== "number" || !Number.isFinite(value)) {
    return "-";
  }
  const prefix = value > 0 ? "+" : "";
  return `${prefix}${value.toFixed(2)}%`;
}

function toRatioText(value: unknown) {
  if (typeof value !== "number" || !Number.isFinite(value)) {
    return "-";
  }
  return `${value.toFixed(2)}배`;
}

function toSignalLabel(signal: unknown) {
  const normalized = String(signal ?? "").toLowerCase();
  if (normalized === "buy") return "매수";
  if (normalized === "sell") return "매도";
  if (normalized === "hold") return "대기";
  return "판단";
}

function toSideLabel(side: unknown) {
  const normalized = String(side ?? "").toLowerCase();
  if (normalized === "buy") return "매수";
  if (normalized === "sell") return "매도";
  return "주문";
}

function toQuantityText(quantity: unknown) {
  if (typeof quantity !== "number" || !Number.isFinite(quantity) || quantity <= 0) {
    return "-";
  }
  return `${Math.floor(quantity).toLocaleString("ko-KR")}주`;
}

function extractFirstReason(detail: Record<string, unknown> | null) {
  if (!detail) return undefined;
  const reasons = detail.blockers ?? detail.blockedReasons;
  if (Array.isArray(reasons) && reasons.length > 0) {
    return String(reasons[0]);
  }
  return undefined;
}

function resolveStatusBadgeVariant(
  state: "IDLE" | "RUNNING" | "STOPPING" | "STOPPED" | "ERROR",
): "default" | "secondary" | "destructive" | "outline" {
  if (state === "RUNNING") return "default";
  if (state === "STOPPING" || state === "ERROR") return "destructive";
  if (state === "STOPPED") return "secondary";
  return "outline";
}

function resolveFriendlyAiModeDescription(
  mode: (typeof AUTOTRADE_AI_MODE_OPTIONS)[number]["id"],
) {
  if (mode === "auto") {
    return "자동으로 가장 사용 가능한 AI를 선택합니다. 초보자에게 추천합니다.";
  }
  if (mode === "openai_api") {
    return "OpenAI API 키를 사용해 판단합니다. 응답 품질을 일정하게 유지하기 좋습니다.";
  }
  if (mode === "subscription_cli") {
    return "Codex/Gemini CLI를 사용해 판단합니다. 모델을 직접 고르고 싶을 때 좋습니다.";
  }
  return "AI 호출 없이 내부 규칙만으로 동작합니다. 가장 보수적인 모드입니다.";
}
