// Stocks.jsx — 주식 메인.

// 추천종목 → Detail item 변환 (STOCK_RISK_MAP에서 실시간 리스크 조회)
function recoToItem(r) {
  const live = (typeof STOCK_RISK_MAP !== 'undefined') ? (STOCK_RISK_MAP[r.ticker] || null) : null;
  return {
    asset: '주식', isin: r.ticker, ledger: '—', name: r.name, ccy: 'KRW',
    type: r.sector,
    status: live ? live.status : '적정',
    cvar:    live ? +(live.risk / 100).toFixed(4) : 0.05,
    dod:     live ? +(live.dod  / 100).toFixed(4) : 0,
    pending: !live,
    note: null,
    stock: {
      ticker: r.ticker, name: r.name, eval: 0,
      ret:     live ? live.ret  : 0,
      risk:    live ? live.risk : 5,
      dod:     live ? live.dod  : 0,
      sector: r.sector, status: live ? live.status : '적정',
      riskAmt: 0, note: null,
    },
  };
}

const STOCK_SECTOR_COLORS = ['#0A4FA3', '#00A0E0', '#6D5BD0', '#11865B', '#E0922A', '#C8363C', '#4F6272', '#8B5CF6', '#0E8C8C'];

// 주식 전용 상태 색상 규칙
const SST = {
  '안전': { fg: '#1DB56C', bg: '#DCF6ED', line: '#A8E6C8' },
  '적정': { fg: '#F98701', bg: '#FFEFD4', line: '#FFD9A0' },
  '주의': { fg: '#FF3D00', bg: '#FFE4D9', line: '#FFBFAA' },
  '위험': { fg: '#FF1C27', bg: '#FFE0E5', line: '#FFB3BC' },
};
const sstColor = (status) => (SST[status] || SST['적정']).fg;

function StockPill({ status }) {
  const s = SST[status] || SST['적정'];
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5,
      background: s.bg, color: s.fg, border: '1px solid ' + s.line,
      borderRadius: 999, padding: '2px 8px',
      fontFamily: T.font, fontWeight: 700, fontSize: 10.5, whiteSpace: 'nowrap' }}>
      <span style={{ width: 6, height: 6, borderRadius: 999, background: s.fg }} />
      {status}
    </span>
  );
}

function PortfolioHero({ p, retLabel = '가중 수익률', extra }) {
  const metrics = [
  { label: retLabel, render: <Delta v={p.ret} suffix="%" digits={1} size={30} />, sub: '보유 기간 평가 기준' },
  { label: '포트폴리오 리스크', value: p.risk, unit: '%', color: T.c900, sub: 'CVaR 99% / 1일 · 평가액 대비' },
  { label: '구성 비중', value: p.weight, unit: '%', color: T.blue, sub: `전체 유가증권 중 · ${(p.hold / 10000).toFixed(1)}조원` }];

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr' + (extra ? ' 1fr' : ''), gap: 12 }}>
      {metrics.map((m, i) =>
      <Card key={i} pad="16px 18px">
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: "center", gap: "50px" }}>
            <div style={{ flex: 'none', display: 'flex', alignItems: 'baseline', gap: 4 }}>
              {m.render || <React.Fragment><span className="num" style={{ fontFamily: T.font, fontWeight: 800, fontSize: 30, color: m.color, letterSpacing: '-.02em' }}>{m.value}</span><span style={{ fontFamily: T.font, fontWeight: 700, fontSize: 15, color: T.c400 }}>{m.unit}</span></React.Fragment>}
            </div>
            <div style={{ width: 1, alignSelf: 'stretch', background: T.line, margin: '2px 0' }} />
            <div style={{ minWidth: 0, display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 4 }}>
              <div style={{ fontFamily: T.font, fontWeight: 700, fontSize: 13, color: T.c700 }}>{m.label}</div>
              <div style={{ fontFamily: T.font, fontWeight: 500, fontSize: 11, color: T.c400 }}>{m.sub}</div>
            </div>
          </div>
        </Card>
      )}
      {extra}
    </div>);

}

function Stocks({ openDetail }) {
  const p = PORTFOLIO.stock;
  const [q, setQ] = React.useState('');
  const [filter, setFilter] = React.useState('전체');
  const sectorComp = React.useMemo(() => Object.entries(STOCK_SEC_COMP).sort((a, b) => b[1] - a[1]).
  map(([label, value], i) => ({ label, value, color: STOCK_SECTOR_COLORS[i % STOCK_SECTOR_COLORS.length] })), []);
  const statusCounts = { 전체: STOCKS.length, 안전: STOCKS.filter((s) => s.status === '안전').length, 적정: STOCKS.filter((s) => s.status === '적정').length, 주의: STOCKS.filter((s) => s.status === '주의').length, 위험: STOCKS.filter((s) => s.status === '위험').length };

  const rows = STOCKS.filter((s) => {
    if (filter !== '전체' && s.status !== filter) return false;
    // 구형 더미 상태도 호환: '정상'→'안전', '유보'→'적정'으로 표시 허용
    if (q && !(s.name.includes(q) || s.ticker.includes(q) || s.sector.includes(q))) return false;
    return true;
  }).map((s) => ({ ...s, _key: s.ticker, weight: +(s.eval / p.hold * 100).toFixed(1), item: { asset: '주식', isin: s.ticker, ledger: '—', name: s.name, ccy: 'KRW', type: s.sector, cvar: +(s.risk / 100).toFixed(4), dod: +(s.dod / 100 * 0.3).toFixed(4), status: s.status, pending: false, stock: s } }));

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <PortfolioHero p={p} />

      <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 16, alignItems: 'start' }}>
        <Card>
          <CardHead title="섹터 구성 비중" sub="평가금액 기준 보유 비중" icon="pie"
          right={<RegTag>평가액 {(p.hold / 10000).toFixed(1)}조</RegTag>} />
          <div style={{ padding: '18px 20px 20px', height: "278px" }}>
            <Donut data={sectorComp} size={172} thick={26} centerTop="보유 종목" centerBig={STOCKS.length} unit="개" />
          </div>
        </Card>
        <Card style={{ display: 'flex', flexDirection: 'column' }}>
          <CardHead title="수익·리스크 분포" sub="종목별 수익률 vs 리스크" icon="target" />
          <div style={{ padding: '16px 18px 18px', flex: 1 }}>
            <ScatterRiskReturn stocks={STOCKS} onPick={(s) => openDetail({ asset: '주식', isin: s.ticker, name: s.name, ccy: 'KRW', type: s.sector, cvar: +(s.risk / 100).toFixed(4), dod: 0, status: s.status, pending: false, stock: s })} />
          </div>
        </Card>
      </div>

      <Card>
        <CardHead title="보유 종목" sub={`현재 구성 종목 ${STOCKS.length}개`} icon="briefcase"
        right={<Search value={q} onChange={setQ} placeholder="티커·종목명 검색" w={220} />} />
        <div style={{ padding: '12px 16px', borderBottom: '1px solid ' + T.line, display: 'flex', alignItems: 'center', gap: 10 }}>
          <Chips value={filter} onChange={setFilter} options={[
          { v: '전체', l: '전체', count: statusCounts.전체 }, { v: '안전', l: '안전', count: statusCounts.안전 }, { v: '적정', l: '적정', count: statusCounts.적정 }, { v: '주의', l: '주의', count: statusCounts.주의 }, { v: '위험', l: '위험', count: statusCounts.위험 }]} />
          <span style={{ marginLeft: 'auto', fontFamily: T.font, fontWeight: 500, fontSize: 11.5, color: T.c400 }}>{rows.length}개 표시 · 헤더 클릭 정렬</span>
        </div>
        <DataTable dense onRow={(r) => openDetail(r.item)}
        initialSort={{ k: 'eval', dir: 'desc' }}
        rows={rows}
        cols={[
        { k: 'ticker', t: '티커', w: 72, render: (r) => <span className="mono" style={{ fontFamily: T.mono, fontSize: 11.5, color: T.c500 }}>{r.ticker}</span> },
        { k: 'name', t: '종목명', w: '18%', render: (r) => <span style={{ fontWeight: 600, color: T.c900 }}>{r.name}</span> },
        { k: 'sector', t: '섹터', render: (r) => <span style={{ color: T.c500 }}>{r.sector}</span> },
        { k: 'eval', t: '평가금액(억)', num: true, render: (r) => <span className="num" style={{ fontWeight: 600, color: T.c800 }}>{r.eval.toLocaleString()}</span> },
        { k: 'weight', t: '비중', num: true, render: (r) => <span className="num" style={{ color: T.c600 }}>{r.weight}%</span> },
        { k: 'ret', t: '수익률', num: true, render: (r) => <Delta v={r.ret} suffix="%" digits={1} />, sortVal: (r) => r.ret },
        { k: 'risk', t: '리스크(CVaR)', num: true, render: (r) => <b className="num" style={{ color: r.risk >= 5 ? T.warn : T.c800 }}>{r.risk.toFixed(1)}%</b> },
        { k: 'dod', t: '전일대비', num: true, render: (r) => <Delta v={r.dod} suffix="%" digits={1} />, sortVal: (r) => r.dod },
        { k: 'status', t: '상태', w: 72, render: (r) => <StockPill status={r.status} /> }]
        } />
      </Card>

      <Card>
        <CardHead title="추천 신규 종목" sub="AI 모델이 산출한 종합 점수 순 · 미보유 종목 · 행 클릭 시 상세 조회" icon="sparkles"
        right={<Pill kind="blue" icon="sparkles">AI 모델 추천</Pill>} />
        <DataTable dense
        initialSort={{ k: 'score', dir: 'desc' }}
        onRow={(r) => openDetail(recoToItem(r))}
        rows={STOCK_RECO.map((r) => ({ ...r, _key: r.ticker }))}
        cols={[
        { k: 'ticker', t: '티커', w: 72, render: (r) => <span className="mono" style={{ fontFamily: T.mono, fontSize: 11.5, color: T.c500 }}>{r.ticker}</span> },
        { k: 'name', t: '종목명', w: '16%', render: (r) => <span style={{ fontWeight: 600, color: T.c900 }}>{r.name}</span> },
        { k: 'sector', t: '섹터', render: (r) => <span style={{ color: T.c500 }}>{r.sector}</span> },
        { k: 'score', t: '추천 점수', num: true, render: (r) => {const c = r.score >= 92 ? T.ok : r.score >= 90 ? T.blue : T.warn;return <span style={{ display: 'inline-flex', alignItems: 'center', gap: 9, justifyContent: 'flex-end' }}><span style={{ width: 60 }}><MeterBar pct={(r.score - 80) / 20 * 100} color={c} /></span><b className="num" style={{ ...{ color: c, width: 38, textAlign: 'right', fontSize: 13.5 }, color: "rgb(10, 79, 163)" }}>{r.score}점</b></span>;}, sortVal: (r) => r.score },
        { k: 'reason', t: '추천 사유', w: '40%', sortable: false, render: (r) => <span style={{ color: T.c600, fontWeight: 500, whiteSpace: 'normal' }}>{r.reason}</span> },
        { k: 'act', t: '', w: 88, sortable: false, render: (r) => <Btn variant="secondary" size="sm" icon="arrowUpRight" onClick={(e) => { e.stopPropagation(); openDetail(recoToItem(r)); }}>상세보기</Btn> }]
        } />
      </Card>
    </div>);

}

// risk-return scatter (mini)
function ScatterRiskReturn({ stocks, onPick }) {
  const w = 460, h = 224, padL = 44, padR = 14, padT = 16, padB = 44;
  const iw = w - padL - padR, ih = h - padT - padB;

  // ── 데이터 기반 동적 스케일 ───────────────────────────────────────────────
  const risks = stocks.map(s => s.risk);
  const rets  = stocks.map(s => s.ret);
  const xPad  = (v) => v * 0.18;           // 양끝에 여백 18%
  const yPad  = (v) => Math.max(v * 0.22, 2);

  const xMin = Math.min(...risks); const xMax = Math.max(...risks);
  const yMin = Math.min(...rets);  const yMax = Math.max(...rets);
  const xSpan = xMax - xMin || 1;  const ySpan = yMax - yMin || 1;
  const xr = [xMin - xPad(xSpan), xMax + xPad(xSpan)];
  const yr = [yMin - yPad(ySpan), yMax + yPad(ySpan)];

  const x = (v) => padL + (v - xr[0]) / (xr[1] - xr[0]) * iw;
  const y = (v) => padT + ih - (v - yr[0]) / (yr[1] - yr[0]) * ih;

  // ── 눈금 자동 생성 ────────────────────────────────────────────────────────
  const niceTick = (min, max, n) => {
    const raw = (max - min) / (n - 1);
    const mag = Math.pow(10, Math.floor(Math.log10(raw)));
    const step = [1,2,2.5,5,10].map(f => f * mag).find(f => f >= raw) || raw;
    const start = Math.ceil(min / step) * step;
    const ticks = [];
    for (let t = start; t <= max + step * 0.01; t = +(t + step).toFixed(10)) ticks.push(+t.toFixed(4));
    return ticks;
  };
  const xTicks = niceTick(xr[0], xr[1], 5);
  const yTicks = niceTick(yr[0], yr[1], 4);
  const fmt = (v) => Number.isInteger(v) ? v : v.toFixed(1);

  return (
    <svg width="100%" viewBox={`0 0 ${w} ${h}`} style={{ display: 'block' }}>
      {/* Y 그리드·눈금 */}
      {yTicks.map((g) => <g key={g}>
        <line x1={padL} y1={y(g)} x2={w - padR} y2={y(g)}
          stroke={Math.abs(g) < 0.01 ? T.c300 : T.c150}
          strokeDasharray={Math.abs(g) < 0.01 ? '0' : '3 3'} />
        <text x={padL - 6} y={y(g) + 3.5} textAnchor="end"
          fontFamily={T.font} fontSize="9" fontWeight="600" fill={T.c400}>{fmt(g)}%</text>
      </g>)}
      {/* X 눈금 */}
      {xTicks.map((g) => <text key={g} x={x(g)} y={padT + ih + 16}
        textAnchor="middle" fontFamily={T.font} fontSize="9" fontWeight="600" fill={T.c400}>{fmt(g)}%</text>)}
      {/* 축 레이블 */}
      <text x={4} y={padT + 4} textAnchor="start" fontFamily={T.font} fontSize="10" fontWeight="700" fill={T.c500}>수익률</text>
      <text x={w - padR} y={padT + ih + 33} textAnchor="end" fontFamily={T.font} fontSize="10" fontWeight="700" fill={T.c500}>리스크</text>
      {/* 종목 점 */}
      {stocks.map((s) => {
        const c = sstColor(s.status);
        const r = Math.max(5, Math.sqrt(s.eval) / 7);
        return <g key={s.ticker} style={{ cursor: 'pointer' }} onClick={() => onPick(s)}>
          <circle cx={x(s.risk)} cy={y(s.ret)} r={r} fill={c} fillOpacity=".22" stroke={c} strokeWidth="1.8" />
          <text x={x(s.risk)} y={y(s.ret) - r - 3} textAnchor="middle"
            fontFamily={T.font} fontSize="9" fontWeight="700" fill={c}>
            {s.name.length > 4 ? s.name.slice(0, 4) : s.name}
          </text>
        </g>;
      })}
    </svg>);

}
Object.assign(window, { Stocks, PortfolioHero, ScatterRiskReturn });
