/**
 * 매수 / 매도 주문 폼 (업비트 스타일)
 */
import React, { useState, useEffect, useCallback, useRef } from 'react';
import ReactDOM from 'react-dom';
import { getKoreanName } from '../utils/marketNameCache';
import { MarketSearchPanel } from './MarketSearchPanel';
import type { TradeOrderFillRequest } from '../types';
import { placePaperOrder } from '../utils/backendApi';
import { coerceFiniteNumber } from '../utils/safeFormat';

export type OrderKind = 'limit' | 'market' | 'stop_limit';

export interface TradeOrderPanelProps {
  side: 'buy' | 'sell';
  market: string;
  /** 현재가 (KRW) — 종목 변경 시 초기값 */
  tradePrice: number | null;
  availableKrw?: number;
  /** 매도 시 보유 수량 (모의투자) */
  availableCoinQty?: number;
  /** 호가·차트에서 자동 입력 */
  fillRequest?: TradeOrderFillRequest | null;
  /** 종목 검색 패널 앵커 (우측 매수·매도 영역) */
  searchAnchorRef?: React.RefObject<HTMLElement | null>;
  /** 종목 변경 시 차트·호가 연동 */
  onMarketSelect?: (market: string) => void;
  /** 매매 통합 탭에서 매도 블록은 종목 필드 숨김 (매수 블록에만 표시) */
  showSymbolField?: boolean;
  /** 모의투자 활성화 시 주문이 가상 계좌로 체결됨 */
  paperTradingEnabled?: boolean;
  /** 모의투자 자동매매 (OFF면 수동 주문만) */
  paperAutoTradeEnabled?: boolean;
  /** 모의 체결 후 잔고 갱신 */
  onPaperOrderFilled?: () => void;
}

export function fmtKrw(n: number): string {
  if (!Number.isFinite(n)) return '0';
  return Math.round(n).toLocaleString('ko-KR');
}

function parseNum(s: string): number {
  const v = Number(String(s).replace(/,/g, '').trim());
  return Number.isFinite(v) ? v : 0;
}

/** KRW 가격: 숫자만 허용, 천 단위 쉼표 표시 */
function sanitizePriceInput(raw: string): string {
  const digits = raw.replace(/\D/g, '');
  if (!digits) return '';
  return Number(digits).toLocaleString('ko-KR');
}

/** 주문 수량: 숫자와 소수점(1개)만 허용 */
function sanitizeQtyInput(raw: string): string {
  let s = raw.replace(/[^\d.]/g, '');
  const dot = s.indexOf('.');
  if (dot !== -1) {
    s = s.slice(0, dot + 1) + s.slice(dot + 1).replace(/\./g, '');
  }
  return s;
}

function coinCode(market: string): string {
  return market.replace(/^KRW-/, '');
}

function priceStep(price: number): number {
  if (price >= 2_000_000) return 1000;
  if (price >= 200_000) return 100;
  if (price >= 20_000) return 10;
  if (price >= 2_000) return 1;
  if (price >= 200) return 0.1;
  if (price >= 20) return 0.01;
  return 0.0001;
}

const ORDER_KINDS: { id: OrderKind; label: string }[] = [
  { id: 'limit', label: '지정가' },
  { id: 'market', label: '시장가' },
  { id: 'stop_limit', label: '예약-지정가' },
];

const PCT_BTNS = [10, 25, 50, 100] as const;

const TradeOrderPanel: React.FC<TradeOrderPanelProps> = ({
  side,
  market,
  tradePrice,
  availableKrw = 0,
  availableCoinQty = 0,
  fillRequest,
  searchAnchorRef,
  onMarketSelect,
  showSymbolField = true,
  paperTradingEnabled = false,
  paperAutoTradeEnabled = false,
  onPaperOrderFilled,
}) => {
  const isBuy = side === 'buy';
  const displayMarket = (fillRequest?.side === side ? fillRequest.market : null) ?? market;
  const code = coinCode(displayMarket);
  const koreanName = getKoreanName(displayMarket);

  const [orderKind, setOrderKind] = useState<OrderKind>('limit');
  const [priceStr, setPriceStr] = useState('');
  const [qtyStr, setQtyStr] = useState('');
  const [totalStr, setTotalStr] = useState('0');
  const [pctMode, setPctMode] = useState<number | null>(null);
  const [showSymbolSearch, setShowSymbolSearch] = useState(false);
  const [symbolQuery, setSymbolQuery] = useState('');
  const symbolInputRef = useRef<HTMLInputElement>(null);

  const openSymbolSearch = useCallback((q = '') => {
    setSymbolQuery(q);
    setShowSymbolSearch(true);
  }, []);

  const handleSymbolSelect = useCallback((m: string) => {
    onMarketSelect?.(m);
    setShowSymbolSearch(false);
    setSymbolQuery('');
    symbolInputRef.current?.blur();
  }, [onMarketSelect]);

  const symbolDisplay = koreanName && koreanName !== displayMarket
    ? `${koreanName} (${code})`
    : (code || displayMarket);

  useEffect(() => {
    if (fillRequest && fillRequest.side === side) {
      setPriceStr(fmtKrw(fillRequest.price));
      setPctMode(null);
      return;
    }
    if (tradePrice != null && tradePrice > 0) {
      setPriceStr(fmtKrw(tradePrice));
    }
  }, [market, tradePrice, fillRequest?.seq, fillRequest?.side, fillRequest?.market, side]);

  const price = parseNum(priceStr);
  const qty = parseNum(qtyStr);
  const refPrice = coerceFiniteNumber(tradePrice) ?? 0;
  const step = priceStep(price > 0 ? price : refPrice);

  useEffect(() => {
    if (orderKind === 'market') {
      setTotalStr(availableKrw > 0 ? fmtKrw(availableKrw) : '0');
      return;
    }
    const total = price * qty;
    setTotalStr(total > 0 ? fmtKrw(total) : '0');
  }, [price, qty, orderKind, availableKrw]);

  const applyPct = useCallback((pct: number) => {
    setPctMode(pct);
    if (isBuy) {
      if (orderKind === 'market' || availableKrw <= 0) return;
      const budget = (availableKrw * pct) / 100;
      const p = orderKind === 'limit' && price > 0 ? price : refPrice;
      if (p > 0) {
        const q = budget / p;
        setQtyStr(q >= 1 ? q.toFixed(8).replace(/\.?0+$/, '') : q.toFixed(8));
      }
      return;
    }
    if (availableCoinQty <= 0) return;
    const q = (availableCoinQty * pct) / 100;
    setQtyStr(q >= 1 ? q.toFixed(8).replace(/\.?0+$/, '') : q.toFixed(8));
  }, [isBuy, availableKrw, availableCoinQty, orderKind, price, refPrice]);

  const bumpPrice = useCallback((delta: number) => {
    const base = price > 0 ? price : refPrice;
    const next = Math.max(0, base + delta);
    setPriceStr(fmtKrw(next));
  }, [price, refPrice]);

  const handleReset = useCallback(() => {
    setOrderKind('limit');
    setQtyStr('');
    setTotalStr('0');
    setPctMode(null);
    if (tradePrice != null && tradePrice > 0) {
      setPriceStr(fmtKrw(tradePrice));
    } else {
      setPriceStr('');
    }
  }, [tradePrice]);

  const handleSubmit = useCallback(async () => {
    const label = isBuy ? '매수' : '매도';
    const execPrice = orderKind === 'market' && tradePrice != null && tradePrice > 0
      ? tradePrice
      : price;
    if (!paperTradingEnabled) {
      window.alert('모의투자가 비활성화되어 있습니다. 설정 → 모의투자에서 사용을 켜 주세요.');
      return;
    }
    if (execPrice <= 0 || qty <= 0) {
      window.alert('가격과 수량을 입력해 주세요.');
      return;
    }
    try {
      const trade = await placePaperOrder({
        market: displayMarket,
        side: isBuy ? 'BUY' : 'SELL',
        orderKind: orderKind === 'market' ? 'market' : 'limit',
        price: execPrice,
        quantity: qty,
        source: 'MANUAL',
      });
      if (!trade) {
        window.alert('모의 주문에 실패했습니다.');
        return;
      }
      onPaperOrderFilled?.();
      window.alert(
        `[모의투자] ${koreanName || code} ${label} 체결\n` +
        `가격: ${fmtKrw(trade.price)} KRW\n` +
        `수량: ${trade.quantity} ${code}\n` +
        `수수료: ${fmtKrw(trade.feeAmount)} KRW\n` +
        `체결 후 현금: ${fmtKrw(trade.cashAfter)} KRW`,
      );
      setQtyStr('');
      setPctMode(null);
    } catch (e) {
      window.alert(e instanceof Error ? e.message : '모의 주문 처리 중 오류가 발생했습니다.');
    }
  }, [
    isBuy, koreanName, code, orderKind, priceStr, qtyStr, totalStr, paperTradingEnabled,
    displayMarket, orderKind, price, qty, tradePrice, onPaperOrderFilled,
  ]);

  const handlePriceChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    setPriceStr(sanitizePriceInput(e.target.value));
  }, []);

  const handleQtyChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    setPctMode(null);
    setQtyStr(sanitizeQtyInput(e.target.value));
  }, []);

  const priceLabel = isBuy ? '매수가격' : '매도가격';
  const minOrder = 5000;
  const feeRate = 0.05;

  return (
    <div className={`top-panel top-panel--${side}`}>
      <div className="top-panel-fields">
      {paperTradingEnabled && !paperAutoTradeEnabled && showSymbolField && (
        <p className="top-paper-hint">자동매매 OFF · 수동 주문만 모의 계좌에 체결됩니다.</p>
      )}
      {showSymbolField && (
        <div className="top-field">
          <label className="top-label">종목</label>
          <div className="top-symbol-field">
            <input
              ref={symbolInputRef}
              type="text"
              className="top-symbol-input"
              value={showSymbolSearch ? symbolQuery : symbolDisplay}
              placeholder="종목명/심볼 검색"
              onFocus={() => openSymbolSearch('')}
              onChange={e => openSymbolSearch(e.target.value)}
              onKeyDown={e => {
                if (e.key === 'Escape') {
                  setShowSymbolSearch(false);
                  setSymbolQuery('');
                }
              }}
            />
            <button
              type="button"
              className="top-symbol-search-btn"
              title="종목 검색"
              onClick={() => {
                openSymbolSearch(symbolQuery);
                symbolInputRef.current?.focus();
              }}
            >
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
              </svg>
            </button>
          </div>
          {showSymbolSearch && ReactDOM.createPortal(
            <MarketSearchPanel
              currentMarket={displayMarket}
              initialQuery={symbolQuery}
              onSelect={handleSymbolSelect}
              onClose={() => { setShowSymbolSearch(false); setSymbolQuery(''); }}
              anchorRect={searchAnchorRef?.current?.getBoundingClientRect() ?? null}
            />,
            document.body,
          )}
        </div>
      )}

      <div className="top-field">
        <label className="top-label">
          주문유형
          <span className="top-label-help" title="주문 유형 안내">?</span>
        </label>
        <div className="top-order-kind">
          {ORDER_KINDS.map(k => (
            <button
              key={k.id}
              type="button"
              className={`top-kind-btn${orderKind === k.id ? ' top-kind-btn--active' : ''}${k.id === 'stop_limit' ? ' top-kind-btn--wide' : ''}`}
              onClick={() => setOrderKind(k.id)}
            >
              {k.label}
              {k.id === 'stop_limit' && <span className="top-kind-arrow">▾</span>}
            </button>
          ))}
        </div>
      </div>

      <div className="top-row top-row--balance">
        <span className="top-label">{isBuy ? '주문가능' : '보유수량'}</span>
        <span className="top-balance">
          {isBuy
            ? `${fmtKrw(availableKrw)} KRW`
            : `${availableCoinQty > 0 ? availableCoinQty.toFixed(8).replace(/\.?0+$/, '') : '0'} ${code}`}
        </span>
      </div>

      <div className="top-price-qty-block">
        <div className="top-field top-field--price">
          <label className="top-label">{priceLabel} (KRW)</label>
          <div className="top-input-group">
            <input
              type="text"
              className="top-input"
              value={priceStr}
              disabled={orderKind === 'market'}
              onChange={handlePriceChange}
              inputMode="numeric"
              pattern="[0-9,]*"
              autoComplete="off"
            />
            <button type="button" className="top-step" onClick={() => bumpPrice(-step)} disabled={orderKind === 'market'}>−</button>
            <button type="button" className="top-step" onClick={() => bumpPrice(step)} disabled={orderKind === 'market'}>+</button>
          </div>
        </div>

        <div className="top-field top-field--qty">
          <label className="top-label">주문수량 ({code})</label>
          <input
            type="text"
            className="top-input top-input--full"
            value={qtyStr}
            disabled={orderKind === 'market'}
            onChange={handleQtyChange}
            inputMode="decimal"
            pattern="[0-9.]*"
            autoComplete="off"
            placeholder="0"
          />
        </div>

        <div className="top-pct-row top-pct-row--block">
          {PCT_BTNS.map(p => (
            <button
              key={p}
              type="button"
              className={`top-pct-btn${pctMode === p ? ' top-pct-btn--active' : ''}`}
              onClick={() => applyPct(p)}
            >
              {p === 100 ? '최대' : `${p}%`}
            </button>
          ))}
          <button
            type="button"
            className={`top-pct-btn top-pct-btn--direct${pctMode === -1 ? ' top-pct-btn--active' : ''}`}
            onClick={() => setPctMode(-1)}
          >
            직접입력
          </button>
        </div>
      </div>

      <div className="top-field">
        <label className="top-label">주문총액 (KRW)</label>
        <input
          type="text"
          className="top-input top-input--full top-input--readonly"
          value={totalStr}
          readOnly
        />
      </div>

      <div className="top-meta">
        <span className="top-meta-line">
          <span>조건: 보통 ▾</span>
          <span className="top-meta-sep">·</span>
          <span>최소 {fmtKrw(minOrder)}</span>
          <span className="top-meta-sep">·</span>
          <span>수수료 {feeRate}%</span>
        </span>
      </div>
      </div>

      <div className="top-actions">
        <button type="button" className="top-reset" onClick={handleReset}>
          <span className="top-reset-icon">↺</span>
          초기화
        </button>
        <button
          type="button"
          className={`top-submit top-submit--${side}`}
          onClick={handleSubmit}
        >
          {isBuy ? '매수' : '매도'}
        </button>
      </div>
    </div>
  );
};

export default TradeOrderPanel;
