/**
 * 좌측 마켓 패널
 *
 * 탭 구성:
 *  원화 - KRW 마켓 목록, 현재가(KRW)
 *  BTC  - KRW 마켓 목록, 현재가(USD 환산)
 *  보유 - 보유 종목 목록 (localStorage 관리)
 *  관심 - 즐겨찾기 목록 (localStorage 관리)
 */
import React, { useState, useCallback, useMemo, useRef, useEffect, memo } from 'react';
import type { TickerData, ChangeDir } from '../hooks/useMarketTicker';
import {
  getFavorites, saveFavorites, toggleFavorite,
  getHoldings, addHolding, removeHolding,
} from '../utils/marketStorage';
// ─── 타입 ──────────────────────────────────────────────────────────────────
type Tab = 'krw' | 'btc' | 'hold' | 'fav';
type SortKey = 'name' | 'price' | 'change';
type SortDir = 'asc' | 'desc';

export interface MarketPanelProps {
  open:           boolean;
  tickers:        Map<string, TickerData>;
  loading:        boolean;
  usdRate:        number;          // KRW per 1 USD (from KRW-USDT)
  activeSymbol:   string;
  onSymbolSelect: (symbol: string) => void;
}

// ─── 가격 포맷 헬퍼 ────────────────────────────────────────────────────────
function fmtKrw(price: number | null | undefined): string {
  if (price == null || !isFinite(price)) return '-';
  if (price >= 1_000_000) return price.toLocaleString('ko-KR', { maximumFractionDigits: 0 });
  if (price >= 1_000)     return price.toLocaleString('ko-KR', { maximumFractionDigits: 0 });
  if (price >= 1)         return price.toLocaleString('ko-KR', { maximumFractionDigits: 2 });
  if (price >= 0.01)      return price.toFixed(4);
  return price.toFixed(8);
}

function fmtUsd(krwPrice: number | null | undefined, rate: number): string {
  if (krwPrice == null || !isFinite(krwPrice) || !rate) return '-';
  const usd = krwPrice / rate;
  if (usd >= 10_000) return '$' + usd.toLocaleString('en-US', { maximumFractionDigits: 0 });
  if (usd >= 1)      return '$' + usd.toFixed(2);
  if (usd >= 0.001)  return '$' + usd.toFixed(4);
  return '$' + usd.toFixed(6);
}

function fmtPct(rate: number | null | undefined): string {
  if (rate == null || !isFinite(rate)) return '-';
  const sign = rate >= 0 ? '+' : '';
  return `${sign}${(rate * 100).toFixed(2)}%`;
}

// ─── 방향 지시자 삼각형 ────────────────────────────────────────────────────
const ChangeArrow = memo(function ChangeArrow({ change }: { change: ChangeDir }) {
  if (change === 'RISE') return <span className="mp-arrow mp-arrow--rise">▲</span>;
  if (change === 'FALL') return <span className="mp-arrow mp-arrow--fall">▼</span>;
  return <span className="mp-arrow mp-arrow--even">─</span>;
});

// ─── 개별 행 ───────────────────────────────────────────────────────────────
interface RowProps {
  ticker:       TickerData | undefined;
  market:       string;
  isActive:     boolean;
  isFav:        boolean;
  isHold:       boolean;
  showUsd:      boolean;
  showHoldBtn:  boolean;
  usdRate:      number;
  onSelect:     () => void;
  onToggleFav:  (e: React.MouseEvent) => void;
  onToggleHold: (e: React.MouseEvent) => void;
  onRemoveHold?: (e: React.MouseEvent) => void;
}

const MarketRow = memo(function MarketRow({
  ticker, market, isActive, isFav, isHold,
  showUsd, showHoldBtn, usdRate,
  onSelect, onToggleFav, onToggleHold, onRemoveHold,
}: RowProps) {
  const change: ChangeDir = ticker?.change ?? 'EVEN';
  const code = market.replace(/^KRW-/, '');

  // ── 가격 변동 플래시 (frontend_golden TickerItem 로직) ─────────────────
  const [flashClass, setFlashClass] = useState('');
  const prevPriceRef = useRef<number | null>(null);
  useEffect(() => {
    const price = ticker?.tradePrice ?? null;
    if (price === null) return;
    const prev = prevPriceRef.current;
    if (prev !== null && prev !== price) {
      const cls = price > prev ? 'mp-row--flash-rise' : 'mp-row--flash-fall';
      setFlashClass(cls);
      const t = setTimeout(() => setFlashClass(''), 700);
      prevPriceRef.current = price;
      return () => clearTimeout(t);
    }
    prevPriceRef.current = price;
  }, [ticker?.tradePrice]);

  const colorCls = change === 'RISE' ? 'mp-up' : change === 'FALL' ? 'mp-dn' : 'mp-even';

  return (
    <div
      className={`mp-row ${isActive ? 'mp-row--active' : ''} ${flashClass}`}
      onClick={onSelect}
    >
      {/* 즐겨찾기 별 */}
      <button
        className={`mp-star ${isFav ? 'mp-star--on' : ''}`}
        onClick={onToggleFav}
        title={isFav ? '관심 해제' : '관심 등록'}
      >
        {isFav ? '★' : '☆'}
      </button>

      {/* 이름 + 방향 지시자 */}
      <div className="mp-name">
        <span className="mp-korean-row">
          <ChangeArrow change={change} />
          <span className="mp-korean">{ticker?.koreanName ?? code}</span>
        </span>
        <span className="mp-code">{code}/KRW</span>
      </div>

      {/* 현재가 */}
      <span className={`mp-price ${colorCls}`}>
        {ticker
          ? (showUsd ? fmtUsd(ticker.tradePrice, usdRate) : fmtKrw(ticker.tradePrice))
          : '-'}
      </span>

      {/* 전일대비 */}
      <span className={`mp-change ${colorCls}`}>
        {ticker ? fmtPct(ticker.changeRate) : '-'}
      </span>

      {/* 보유 토글 / 제거 버튼 */}
      {onRemoveHold ? (
        <button className="mp-hold-rm" onClick={onRemoveHold} title="보유 종목 제거">×</button>
      ) : showHoldBtn ? (
        <button
          className={`mp-hold-btn ${isHold ? 'mp-hold-btn--on' : ''}`}
          onClick={onToggleHold}
          title={isHold ? '보유 해제' : '보유 등록'}
        >
          {isHold ? '₩' : '+₩'}
        </button>
      ) : null}
    </div>
  );
});

// ─── 메인 패널 ─────────────────────────────────────────────────────────────
export const MarketPanel: React.FC<MarketPanelProps> = ({
  open, tickers, loading, usdRate, activeSymbol, onSymbolSelect,
}) => {
  const [tab,      setTab]      = useState<Tab>('krw');
  const [search,   setSearch]   = useState('');
  const [favorites,  setFavs]   = useState<string[]>(getFavorites);
  const [holdings,   setHolds]  = useState<string[]>(getHoldings);
  const [holdSearch, setHoldSrch] = useState('');
  const [showHoldAdd, setShowHoldAdd] = useState(false);
  const [sortKey,  setSortKey]  = useState<SortKey | null>(null);
  const [sortDir,  setSortDir]  = useState<SortDir>('desc');
  const searchRef = useRef<HTMLInputElement>(null);

  // 패널 열릴 때 검색창 포커스
  useEffect(() => { if (open) setTimeout(() => searchRef.current?.focus(), 250); }, [open]);

  // 검색 초기화 (탭 전환 시)
  const handleTab = useCallback((t: Tab) => { setTab(t); setSearch(''); }, []);

  // 컬럼 정렬 토글
  const handleSort = useCallback((key: SortKey) => {
    setSortKey(prev => {
      if (prev === key) {
        setSortDir(d => d === 'asc' ? 'desc' : 'asc');
        return key;
      }
      setSortDir('desc');
      return key;
    });
  }, []);

  // 즐겨찾기 토글
  const handleToggleFav = useCallback(async (market: string, e: React.MouseEvent) => {
    e.stopPropagation();
    const row = tickers.get(market);
    try {
      const next = await toggleFavorite(market, { koreanName: row?.koreanName });
      setFavs(next);
    } catch (err) {
      console.warn('[MarketPanel] watchlist toggle failed', err);
    }
  }, [tickers]);

  // 보유 토글
  const handleToggleHold = useCallback((market: string, e: React.MouseEvent) => {
    e.stopPropagation();
    setHolds(prev =>
      prev.includes(market) ? removeHolding(market) : addHolding(market)
    );
  }, []);

  // 보유 제거 (보유 탭)
  const handleRemoveHold = useCallback((market: string, e: React.MouseEvent) => {
    e.stopPropagation();
    setHolds(removeHolding(market));
  }, []);

  // 보유 추가 검색에서 선택
  const handleAddHolding = useCallback((market: string) => {
    setHolds(addHolding(market));
    setHoldSrch('');
    setShowHoldAdd(false);
  }, []);

  // 탭별 마켓 목록 계산
  const allKrwMarkets = useMemo(() => {
    const keys = Array.from(tickers.keys()).filter(m => m.startsWith('KRW-'));
    // 24h 거래대금 내림차순 정렬
    return keys.sort((a, b) =>
      (tickers.get(b)?.accTradePrice24 ?? 0) - (tickers.get(a)?.accTradePrice24 ?? 0)
    );
  }, [tickers]);

  const filtered = useMemo(() => {
    let base: string[] = [];
    switch (tab) {
      case 'krw': case 'btc': base = allKrwMarkets; break;
      case 'hold': base = holdings.filter(m => tickers.has(m) || true); break;
      case 'fav':  base = favorites; break;
    }
    if (search) {
      const q = search.toUpperCase();
      base = base.filter(m => {
        const code = m.replace(/^KRW-/, '');
        const name = tickers.get(m)?.koreanName ?? '';
        return code.includes(q) || name.includes(search);
      });
    }
    if (!sortKey) return base;
    const mul = sortDir === 'asc' ? 1 : -1;
    return [...base].sort((a, b) => {
      const ta = tickers.get(a);
      const tb = tickers.get(b);
      switch (sortKey) {
        case 'name': {
          const na = ta?.koreanName ?? a.replace(/^KRW-/, '');
          const nb = tb?.koreanName ?? b.replace(/^KRW-/, '');
          return mul * na.localeCompare(nb, 'ko');
        }
        case 'price':
          return mul * ((ta?.tradePrice ?? 0) - (tb?.tradePrice ?? 0));
        case 'change':
          return mul * ((ta?.changeRate ?? 0) - (tb?.changeRate ?? 0));
        default:
          return 0;
      }
    });
  }, [tab, allKrwMarkets, holdings, favorites, search, tickers, sortKey, sortDir]);

  // 보유 탭 "추가" 검색 결과
  const holdAddResults = useMemo(() => {
    if (!holdSearch) return [];
    const q = holdSearch.toUpperCase();
    return allKrwMarkets
      .filter(m => {
        const code = m.replace(/^KRW-/, '');
        const name = tickers.get(m)?.koreanName ?? '';
        return code.includes(q) || name.includes(holdSearch);
      })
      .slice(0, 10);
  }, [holdSearch, allKrwMarkets, tickers]);

  const tabLabels: Record<Tab, string> = {
    krw: '원화', btc: 'BTC', hold: '보유', fav: '관심',
  };

  return (
    <div className={`market-panel ${open ? 'market-panel--open' : ''}`}>
      {/* ── 패널 내용 ─────────────────────────────────────────────── */}
      <div className="mp-body mp-body--full">
        {/* 탭 헤더 */}
        <div className="mp-tabs">
          {(['krw', 'btc', 'hold', 'fav'] as Tab[]).map(t => (
            <button
              key={t}
              className={`mp-tab ${tab === t ? 'mp-tab--active' : ''}`}
              onClick={() => handleTab(t)}
            >
              {tabLabels[t]}
            </button>
          ))}
        </div>

        {/* 검색 */}
        <div className="mp-search-row">
          <div className="mp-search-box">
            <svg width="13" height="13" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.5" opacity={0.5}>
              <circle cx="5.5" cy="5.5" r="4"/><line x1="9" y1="9" x2="12.5" y2="12.5"/>
            </svg>
            <input
              ref={searchRef}
              className="mp-search-input"
              type="text"
              placeholder="코인명/심볼검색"
              value={search}
              onChange={e => setSearch(e.target.value)}
            />
            {search && (
              <button className="mp-search-clear" onClick={() => setSearch('')}>✕</button>
            )}
          </div>
        </div>

        {/* 컬럼 헤더 */}
        <div className="mp-list-header">
          {(['name', 'price', 'change'] as SortKey[]).map(key => {
            const label = key === 'name' ? '한글명' : key === 'price' ? '현재가' : '전일대비';
            const cls   = key === 'name' ? 'mp-h-name' : key === 'price' ? 'mp-h-price' : 'mp-h-change';
            const active = sortKey === key;
            return (
              <button
                key={key}
                className={`${cls} mp-h-sort-btn ${active ? 'mp-h-sort-btn--active' : ''}`}
                onClick={() => handleSort(key)}
                title={active ? (sortDir === 'asc' ? '내림차순 정렬' : '오름차순 정렬') : `${label} 정렬`}
              >
                {label}
                <span className="mp-sort-icon">
                  {active ? (sortDir === 'asc' ? '▲' : '▼') : '⇅'}
                </span>
              </button>
            );
          })}
        </div>

        {/* 보유 탭: 추가 버튼 */}
        {tab === 'hold' && (
          <div className="mp-hold-add-area">
            {showHoldAdd ? (
              <div className="mp-hold-add-form">
                <input
                  className="mp-hold-add-input"
                  placeholder="종목 검색..."
                  value={holdSearch}
                  onChange={e => setHoldSrch(e.target.value)}
                  autoFocus
                />
                <button className="mp-hold-add-cancel" onClick={() => { setShowHoldAdd(false); setHoldSrch(''); }}>취소</button>
                {holdAddResults.length > 0 && (
                  <div className="mp-hold-add-dropdown">
                    {holdAddResults.map(m => (
                      <div key={m} className="mp-hold-add-item" onClick={() => handleAddHolding(m)}>
                        <span>{tickers.get(m)?.koreanName ?? m.replace(/^KRW-/, '')}</span>
                        <span className="mp-hold-add-code">{m.replace(/^KRW-/, '')}</span>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            ) : (
              <button className="mp-hold-add-btn" onClick={() => setShowHoldAdd(true)}>
                + 보유 종목 추가
              </button>
            )}
          </div>
        )}

        {/* 마켓 목록 */}
        <div className="mp-list">
          {loading && (
            <div className="mp-loading">
              <div className="loading-spinner" style={{ width: 18, height: 18 }} />
              <span>마켓 정보 로딩 중...</span>
            </div>
          )}

          {!loading && filtered.length === 0 && (
            <div className="mp-empty">
              {tab === 'hold' ? '보유 종목이 없습니다' :
               tab === 'fav'  ? '관심 종목이 없습니다' :
               '검색 결과 없음'}
            </div>
          )}

          {!loading && filtered.map(market => (
            <MarketRow
              key={market}
              market={market}
              ticker={tickers.get(market)}
              isActive={market === activeSymbol}
              isFav={favorites.includes(market)}
              isHold={holdings.includes(market)}
              showUsd={tab === 'btc'}
              showHoldBtn={tab === 'krw' || tab === 'btc' || tab === 'fav'}
              usdRate={usdRate}
              onSelect={() => onSymbolSelect(market)}
              onToggleFav={e => handleToggleFav(market, e)}
              onToggleHold={e => handleToggleHold(market, e)}
              onRemoveHold={tab === 'hold' ? e => handleRemoveHold(market, e) : undefined}
            />
          ))}
        </div>
      </div>

    </div>
  );
};

export default MarketPanel;
