import React, { useCallback, useEffect, useState } from 'react';
import { useDraggablePanel } from '../hooks/useDraggablePanel';
import {
  BacktestSettingsDto,
  DEFAULT_BACKTEST_SETTINGS,
  loadBacktestSettings,
  saveBacktestSettings,
} from '../utils/backendApi';

// ── 설명 메타데이터 ─────────────────────────────────────────────────────────

interface FieldMeta {
  label:       string;
  description: string;
}

const FIELD_META: Partial<Record<keyof BacktestSettingsDto, FieldMeta>> = {
  analysisMethod: {
    label: '투자분석 방식',
    description:
      '수익률·손익 산정 방식을 선택합니다.\n• 평가손익 포함(표준): 예수금 + 보유주식 시가평가. HTS 평가금액과 동일합니다.\n• 실현손익만: 청산 완료 거래의 실현손익만 반영합니다.',
  },
  initialCapital: {
    label: '초기 자본',
    description:
      '백테스팅 시뮬레이션의 시작 자본금(원)입니다. 수익/손실 금액과 최종 자산을 이 금액 기준으로 계산합니다.\n예) 1,000만원 설정 → 총 수익률 +15% 달성 시 최종 자산 = 1,150만원으로 표시됩니다.',
  },
  commissionType: {
    label: '수수료 유형',
    description:
      '매매 수수료 계산 방식을 선택합니다.\n• LINEAR: 거래금액 × 수수료율로 계산합니다. 국내 거래소 현물거래에 적합합니다.\n• ZERO: 수수료 없이 계산합니다. 순수 전략 성과만 검증할 때 사용합니다.',
  },
  commissionRate: {
    label: '수수료율',
    description:
      '매수·매도 각 1회당 부과되는 수수료율입니다.\n예) 0.15% = 0.0015, 거래금액 100만원일 때 수수료 1,500원\n• 업비트 현물: 약 0.05% (0.0005)\n• 빗썸 현물: 약 0.25% (0.0025)\n왕복(매수+매도) 합산 수수료가 손익에서 차감됩니다.',
  },
  slippageRate: {
    label: '슬리피지',
    description:
      '주문을 낼 때 의도한 가격과 실제 체결 가격의 차이 비율입니다.\n• 매수: 목표가보다 슬리피지만큼 높게 체결 (불리)\n• 매도: 목표가보다 슬리피지만큼 낮게 체결 (불리)\n예) 슬리피지 0.05%, 100만원 매수 → 실제 체결 1,000,500원\n거래량이 적거나 변동성이 높을수록 슬리피지가 커집니다.',
  },
  entryPriceType: {
    label: '진입 가격 기준',
    description:
      '매수 신호 발생 시 어느 가격에 진입하는지 결정합니다.\n• CLOSE(종가): 신호 발생 봉의 종가로 즉시 진입. 구현이 단순하지만 후행성(look-ahead bias) 우려가 있습니다.\n• NEXT_OPEN(다음봉 시가): 신호 다음 봉 시가에 진입. 실제 트레이딩과 가장 유사한 현실적 시뮬레이션입니다.',
  },
  exitPriceType: {
    label: '청산 가격 기준',
    description:
      '매도 신호 발생 시 어느 가격에 청산하는지 결정합니다.\n• CLOSE(종가): 신호 발생 봉의 종가로 즉시 청산합니다.\n• NEXT_OPEN(다음봉 시가): 신호 다음 봉 시가에 청산. 야간 갭 하락 등 실제 리스크를 반영합니다.',
  },
  positionDirection: {
    label: '포지션 방향',
    description:
      '어떤 방향의 거래를 시뮬레이션할지 선택합니다.\n• LONG(매수만): 매수 후 가격 상승을 기대하는 전략입니다. 가장 일반적인 방식입니다.\n• SHORT(공매도): 매도 후 가격 하락을 기대합니다. 선물/마진 거래 전략 검증에 사용합니다.\n• BOTH(양방향): 매수 신호는 롱 진입, 매도 신호는 숏 진입으로 처리합니다.',
  },
  tradeSizeType: {
    label: '거래 규모 유형',
    description:
      '매 거래마다 사용할 자금 규모 방식을 선택합니다.\n• CAPITAL_PCT(자본 비율): 현재 보유 자본의 N%를 거래에 사용합니다. 복리 효과가 반영됩니다.\n• FIXED_AMOUNT(고정 금액): 매 거래마다 동일한 금액(원)을 사용합니다. 단리 방식과 유사합니다.',
  },
  tradeSizeValue: {
    label: '거래 규모 값',
    description:
      '자본 비율 선택 시: 매 거래에 사용할 자본 비율(%)입니다.\n예) 100 = 전체 자본 사용, 50 = 절반만 사용\n\n고정 금액 선택 시: 매 거래마다 사용할 원화 금액입니다.\n예) 1,000,000 = 매 거래당 100만원 고정 투자',
  },
  stopLossEnabled: {
    label: '손절 활성화',
    description:
      '진입가 대비 N% 하락 시 자동으로 포지션을 청산하는 기능입니다 (Ta4j StopLossRule).\n전략의 매도 조건보다 손절이 먼저 발동될 경우 손절로 청산됩니다.\n예) 손절 비율 2% 설정, 100만원 매수 → 가격이 98만원으로 하락 시 자동 손절',
  },
  stopLossPct: {
    label: '손절 비율 (%)',
    description:
      '진입가 대비 이 비율만큼 가격이 하락하면 즉시 포지션을 청산합니다.\n예) 2.0 설정 → 진입가 100,000원일 때 98,000원 이하로 하락 시 손절\n낮은 값: 손실 최소화 but 잦은 손절로 기회 상실 가능\n높은 값: 큰 손실 허용 but 반전 기회 포착 가능',
  },
  takeProfitEnabled: {
    label: '익절 활성화',
    description:
      '진입가 대비 N% 상승 시 자동으로 포지션을 청산하는 기능입니다 (Ta4j StopGainRule).\n목표 수익률에 도달하면 확실히 이익을 실현합니다.\n예) 익절 비율 5% 설정, 100만원 매수 → 가격이 105만원으로 상승 시 자동 익절',
  },
  takeProfitPct: {
    label: '익절 비율 (%)',
    description:
      '진입가 대비 이 비율만큼 가격이 상승하면 즉시 포지션을 청산합니다.\n예) 5.0 설정 → 진입가 100,000원일 때 105,000원 이상 상승 시 익절\n낮은 값: 자주 이익 실현 but 대세 상승장 추세 이탈 가능\n높은 값: 큰 수익 추구 but 수익 반납 위험 증가',
  },
  trailingStopEnabled: {
    label: '트레일링 스탑 활성화',
    description:
      '포지션 보유 중 도달한 최고가 대비 N% 하락 시 자동 청산하는 기능입니다 (Ta4j TrailingStopLossRule).\n고정 손절과 달리 추세를 따라 기준점이 올라가므로 상승 추세를 최대한 활용하면서 수익을 보호합니다.\n예) 100만원 매수, 트레일링 2% → 가격이 120만원까지 상승 후 2% 하락한 117.6만원에서 청산',
  },
  trailingStopPct: {
    label: '트레일링 비율 (%)',
    description:
      '포지션 진입 후 기록된 최고가 대비 이 비율만큼 하락하면 청산합니다.\n예) 2.0 설정, 최고가 120,000원 → 117,600원 (= 120,000 × 0.98) 이하 하락 시 청산\n낮은 값: 소폭 하락에도 청산, 수익 보호에 유리\n높은 값: 큰 조정을 허용, 장기 추세 추종에 유리',
  },
  reentryWaitBars: {
    label: '재진입 대기 봉 수',
    description:
      '포지션 청산(매도) 후 다음 매수 신호를 받을 때까지 최소 대기해야 하는 봉(캔들) 수입니다.\n연속 매매를 방지하고 시장이 안정되길 기다리는 효과가 있습니다.\n예) 3 설정 → 매도 후 3봉 동안은 매수 신호 무시\n0: 즉시 재진입 허용 (기본값)',
  },
  maxOpenTrades: {
    label: '최대 동시 포지션',
    description:
      '동시에 보유할 수 있는 최대 포지션(거래) 수입니다.\n현재 구현에서는 단일 포지션(1)만 완전히 지원됩니다.\n1로 설정 시: 이미 포지션을 보유 중이면 새 매수 신호를 무시합니다.',
  },
  partialExitEnabled: {
    label: '분할 청산 활성화',
    description:
      '첫 매도 신호 발생 시 포지션 전부가 아닌 일부만 청산하는 기능입니다.\n리스크를 줄이면서도 나머지 포지션으로 추가 상승을 노릴 수 있습니다.\n예) 분할 청산 50% 설정 → 첫 매도 신호에 50% 청산, 이후 다음 신호 또는 손절/익절 시 나머지 50% 청산',
  },
  partialExitPct: {
    label: '1차 청산 비율 (%)',
    description:
      '첫 번째 매도 신호 발생 시 현재 포지션의 몇 퍼센트를 청산할지 설정합니다.\n예) 50 설정 → 보유량의 절반을 1차 청산, 나머지는 계속 보유\n예) 30 설정 → 보유량의 30%만 1차 청산 (더 공격적 운용)',
  },
};

// ── 섹션 정의 ─────────────────────────────────────────────────────────────

interface SettingField {
  key:  keyof BacktestSettingsDto;
  type: 'number' | 'select' | 'toggle' | 'percent';
  opts?: { value: string; label: string }[];
  min?: number; max?: number; step?: number;
  /** 이 필드가 보이려면 이 조건이 true여야 함 */
  visibleWhen?: (cfg: BacktestSettingsDto) => boolean;
}

interface SettingSection {
  title:  string;
  fields: SettingField[];
}

const SECTIONS: SettingSection[] = [
  {
    title: '📊 투자분석 방식',
    fields: [
      {
        key: 'analysisMethod', type: 'select',
        opts: [
          { value: 'MARK_TO_MARKET', label: '평가손익 포함 (표준)' },
          { value: 'REALIZED_ONLY', label: '실현손익만' },
        ],
      },
    ],
  },
  {
    title: '💰 자본 설정',
    fields: [
      { key: 'initialCapital', type: 'number', min: 100000, step: 1000000 },
    ],
  },
  {
    title: '💸 비용 모델',
    fields: [
      {
        key: 'commissionType', type: 'select',
        opts: [{ value:'LINEAR', label:'LINEAR (비율 수수료)' }, { value:'ZERO', label:'ZERO (수수료 없음)' }],
      },
      { key: 'commissionRate', type: 'percent', min: 0, max: 5, step: 0.01,
        visibleWhen: c => c.commissionType === 'LINEAR' },
      { key: 'slippageRate',   type: 'percent', min: 0, max: 5, step: 0.01 },
    ],
  },
  {
    title: '📈 거래 가격',
    fields: [
      {
        key: 'entryPriceType', type: 'select',
        opts: [{ value:'CLOSE', label:'종가 (Close)' }, { value:'NEXT_OPEN', label:'다음봉 시가 (Next Open)' }],
      },
      {
        key: 'exitPriceType', type: 'select',
        opts: [{ value:'CLOSE', label:'종가 (Close)' }, { value:'NEXT_OPEN', label:'다음봉 시가 (Next Open)' }],
      },
      {
        key: 'positionDirection', type: 'select',
        opts: [
          { value:'LONG',  label:'LONG (매수만)' },
          { value:'SHORT', label:'SHORT (공매도)' },
          { value:'BOTH',  label:'BOTH (양방향)' },
        ],
      },
    ],
  },
  {
    title: '📦 거래 규모',
    fields: [
      {
        key: 'tradeSizeType', type: 'select',
        opts: [{ value:'CAPITAL_PCT', label:'자본 비율 (%)' }, { value:'FIXED_AMOUNT', label:'고정 금액 (원)' }],
      },
      { key: 'tradeSizeValue', type: 'number', min: 1, step: 1 },
    ],
  },
  {
    title: '🛑 손절',
    fields: [
      { key: 'stopLossEnabled', type: 'toggle' },
      { key: 'stopLossPct',     type: 'number', min: 0.1, max: 50, step: 0.1,
        visibleWhen: c => !!c.stopLossEnabled },
    ],
  },
  {
    title: '🎯 익절',
    fields: [
      { key: 'takeProfitEnabled', type: 'toggle' },
      { key: 'takeProfitPct',     type: 'number', min: 0.1, max: 200, step: 0.1,
        visibleWhen: c => !!c.takeProfitEnabled },
    ],
  },
  {
    title: '📉 트레일링 스탑',
    fields: [
      { key: 'trailingStopEnabled', type: 'toggle' },
      { key: 'trailingStopPct',     type: 'number', min: 0.1, max: 50, step: 0.1,
        visibleWhen: c => !!c.trailingStopEnabled },
    ],
  },
  {
    title: '🔁 재진입 제어',
    fields: [
      { key: 'reentryWaitBars', type: 'number', min: 0, max: 100, step: 1 },
      { key: 'maxOpenTrades',   type: 'number', min: 1, max: 10,  step: 1 },
    ],
  },
  {
    title: '✂️ 분할 청산',
    fields: [
      { key: 'partialExitEnabled', type: 'toggle' },
      { key: 'partialExitPct',     type: 'number', min: 10, max: 90, step: 5,
        visibleWhen: c => !!c.partialExitEnabled },
    ],
  },
];

// ── 컴포넌트 ────────────────────────────────────────────────────────────────

interface Props {
  onClose:          () => void;
  onSettingsChange: (s: BacktestSettingsDto) => void;
}

export default function BacktestSettingsModal({ onClose, onSettingsChange }: Props) {
  const [cfg,     setCfg]     = useState<BacktestSettingsDto>(DEFAULT_BACKTEST_SETTINGS);
  const [saving,  setSaving]  = useState(false);
  const [saved,   setSaved]   = useState(false);
  const [focused, setFocused] = useState<keyof BacktestSettingsDto | null>('initialCapital');

  const {
    panelRef: modalRef,
    dragging,
    onHeaderPointerDown, headerTouchStyle,
    panelStyle,
    headerCursor,
  } = useDraggablePanel({ centerOnMount: true });

  // 설정 로드
  useEffect(() => {
    loadBacktestSettings().then(s => { if (s) setCfg(s); });
  }, []);

  const set = <K extends keyof BacktestSettingsDto>(k: K, v: BacktestSettingsDto[K]) =>
    setCfg(prev => ({ ...prev, [k]: v }));

  const handleSave = async () => {
    setSaving(true);
    const result = await saveBacktestSettings(cfg);
    if (result) {
      onSettingsChange({ ...cfg, ...result });
      setSaved(true);
      setTimeout(() => setSaved(false), 1500);
    }
    setSaving(false);
  };

  const focusMeta = focused ? FIELD_META[focused] : null;

  // 모든 섹션의 보이는 필드를 1차원 배열로 수집 (2열 그리드용)
  const allFields: Array<{ section: string; field: SettingField }> = [];
  for (const sec of SECTIONS) {
    for (const f of sec.fields) {
      if (!f.visibleWhen || f.visibleWhen(cfg)) {
        allFields.push({ section: sec.title, field: f });
      }
    }
  }

  return (
    <div
      className="bts-modal"
      ref={modalRef}
      style={{
        ...panelStyle,
        zIndex: 9100,
        cursor: dragging ? 'grabbing' : undefined,
      }}
    >
      {/* ── 타이틀바 (드래그 핸들) ── */}
      <div
        className="gc-popup-header bts-header"
        onPointerDown={onHeaderPointerDown}
        style={{ cursor: headerCursor, ...headerTouchStyle }}
      >
        <svg width="13" height="13" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" style={{opacity:.6}}>
          <circle cx="8" cy="8" r="2.5"/>
          <path d="M8 1.5L8 3.5 M8 12.5L8 14.5 M1.5 8L3.5 8 M12.5 8L14.5 8
                   M3.4 3.4L4.8 4.8 M11.2 11.2L12.6 12.6 M12.6 3.4L11.2 4.8 M4.8 11.2L3.4 12.6"
            strokeLinecap="round"/>
        </svg>
        <span className="bts-title">백테스팅 설정</span>
        <button className="bts-close" onMouseDown={e => e.stopPropagation()} onClick={onClose}>✕</button>
      </div>

      {/* ── 2열 설정 그리드 ── */}
      <div className="bts-body">
        {SECTIONS.map(sec => {
          const visibleFields = sec.fields.filter(f => !f.visibleWhen || f.visibleWhen(cfg));
          if (visibleFields.length === 0) return null;
          return (
            <div key={sec.title} className="bts-section">
              <div className="bts-section-title">{sec.title}</div>
              <div className="bts-section-grid">
                {visibleFields.map(f => (
                  <FieldRow
                    key={f.key}
                    field={f}
                    cfg={cfg}
                    focused={focused}
                    onFocus={setFocused}
                    onChange={set}
                  />
                ))}
              </div>
            </div>
          );
        })}
      </div>

      {/* ── 하단 설명 패널 ── */}
      <div className="bts-desc-panel">
        {focusMeta ? (
          <>
            <span className="bts-desc-label">{focusMeta.label}</span>
            <span className="bts-desc-sep">—</span>
            <span className="bts-desc-text">{focusMeta.description}</span>
          </>
        ) : (
          <span className="bts-desc-placeholder">설정 항목을 클릭하면 상세 설명이 표시됩니다.</span>
        )}
      </div>

      {/* ── 푸터 ── */}
      <div className="bts-footer">
        <button className="bts-btn bts-btn-reset" onClick={() => setCfg(DEFAULT_BACKTEST_SETTINGS)}>
          기본값
        </button>
        <div style={{ flex: 1 }} />
        <button className="bts-btn bts-btn-cancel" onClick={onClose}>취소</button>
        <button className="bts-btn bts-btn-save" onClick={handleSave} disabled={saving}>
          {saving ? '저장 중...' : saved ? '✓ 저장됨' : '확인'}
        </button>
      </div>
    </div>
  );
}

// ── FieldRow ─────────────────────────────────────────────────────────────────

function FieldRow({
  field, cfg, focused, onFocus, onChange,
}: {
  field:    SettingField;
  cfg:      BacktestSettingsDto;
  focused:  keyof BacktestSettingsDto | null;
  onFocus:  (k: keyof BacktestSettingsDto) => void;
  onChange: <K extends keyof BacktestSettingsDto>(k: K, v: BacktestSettingsDto[K]) => void;
}) {
  const meta = FIELD_META[field.key];
  const label = meta?.label ?? field.key;
  const isFocused = focused === field.key;

  const renderCtrl = () => {
    const val = cfg[field.key];
    switch (field.type) {
      case 'toggle':
        return (
          <button
            className={`bts-toggle${val ? ' bts-toggle-on' : ''}`}
            onClick={e => { e.stopPropagation(); onChange(field.key, !val as BacktestSettingsDto[typeof field.key]); }}
          >
            {val ? 'ON' : 'OFF'}
          </button>
        );
      case 'select':
        return (
          <select
            className="bts-select"
            value={String(val)}
            onChange={e => onChange(field.key, e.target.value as BacktestSettingsDto[typeof field.key])}
            onClick={e => e.stopPropagation()}
          >
            {field.opts?.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
          </select>
        );
      case 'percent':
        return (
          <div className="bts-pct-wrap">
            <input
              type="number"
              className="bts-input"
              value={((val as number) * 100).toFixed(3)}
              min={field.min} max={field.max} step={field.step ?? 0.01}
              onChange={e => onChange(field.key, Number(e.target.value) / 100 as BacktestSettingsDto[typeof field.key])}
              onClick={e => e.stopPropagation()}
            />
            <span className="bts-unit">%</span>
          </div>
        );
      default:
        return (
          <input
            type="number"
            className="bts-input"
            value={val as number}
            min={field.min} max={field.max} step={field.step ?? 1}
            onChange={e => onChange(field.key, Number(e.target.value) as BacktestSettingsDto[typeof field.key])}
            onClick={e => e.stopPropagation()}
          />
        );
    }
  };

  return (
    <div
      className={`bts-row${isFocused ? ' bts-row-focused' : ''}`}
      onClick={() => onFocus(field.key)}
    >
      <span className="bts-row-label">{label}</span>
      <span className="bts-row-ctrl">{renderCtrl()}</span>
    </div>
  );
}
