// BondFactor.jsx — 채권 리스크 요인 분석: 기준금리 · 국가/등급 스프레드 · DV01 · 기간구조 · Greeks · 팩터 익스포저.

const bfMn = (v) => Math.round(v * 100).toLocaleString(); // 억 → 백만원
const bfSigned = (v) => (v > 0 ? '+' : v < 0 ? '−' : '') + Math.abs(Math.round(v * 100)).toLocaleString();

// ── ① 나라별 기준금리 ──
function PolicyRates() {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: `repeat(${POLICY_RATES.length},1fr)`, gap: 10 }}>
      {POLICY_RATES.map((p) => {
        const c = p.delta > 0 ? T.up : p.delta < 0 ? T.down : T.c500;
        return (
          <div key={p.country} style={{ border: '1px solid ' + T.line, borderRadius: 10, padding: '11px 13px', background: T.c50, minWidth: 0 }}>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
              <span style={{ fontFamily: T.font, fontWeight: 700, fontSize: 12.5, color: T.c800 }}>{p.country}</span>
              <span style={{ fontFamily: T.mono, fontSize: 9.5, color: T.c400 }}>{p.bank}</span>
            </div>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginTop: 6 }}>
              <span className="num" style={{ fontFamily: T.font, fontWeight: 800, fontSize: 22, color: T.c900, letterSpacing: '-.02em' }}>{p.rate.toFixed(2)}</span>
              <span style={{ fontFamily: T.font, fontWeight: 600, fontSize: 11, color: T.c400 }}>%</span>
              {p.delta !== 0 && <span style={{ marginLeft: 3 }}><Delta v={p.delta} suffix="%p" digits={2} size={11} /></span>}
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 5 }}>
              <span style={{ fontFamily: T.font, fontWeight: 500, fontSize: 10.5, color: p.delta !== 0 ? c : T.c400 }}>{p.asOfMove}</span>
              <span style={{ marginLeft: 'auto', width: 56 }}><Spark data={fvSpark(p.seed, p.rate, p.mvol)} color={c} full w={56} h={22} /></span>
            </div>
          </div>);
      })}
    </div>);
}

// ── ② 국가/등급별 신용스프레드 매트릭스 ──
function SpreadMatrix({ pf }) {
  const held = new Set(pf.holds.map((h) => UMAP[h.id].country));
  const all = SPREAD_MATRIX.flatMap((r) => SPREAD_GRADES.map((g) => r.spreads[g]));
  const mx = Math.max(...all);
  const heat = (v) => { const f = Math.min(1, v / mx); const r = Math.round(249 - (249 - 199) * f), g = Math.round(233 - (233 - 106) * f), b = Math.round(233 - (233 - 31) * f); return `rgb(${r},${g},${b})`; };
  return (
    <div>
      <div style={{ display: 'grid', gridTemplateColumns: '92px repeat(4,1fr)', gap: 5 }}>
        <div />
        {SPREAD_GRADES.map((g) => <div key={g} style={{ fontFamily: T.font, fontWeight: 700, fontSize: 11, color: T.c500, textAlign: 'center', padding: '4px 0' }}>{g}</div>)}
        {SPREAD_MATRIX.map((row) => <React.Fragment key={row.country}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <span style={{ width: 8, height: 8, borderRadius: 3, background: COUNTRY_HUE[row.country] || T.c400, flex: 'none' }} />
            <span style={{ fontFamily: T.font, fontWeight: 700, fontSize: 12, color: T.c700 }}>{row.country}</span>
            {held.has(row.country) && <span title="보유 국가" style={{ width: 5, height: 5, borderRadius: 9, background: T.blue, flex: 'none' }} />}
          </div>
          {SPREAD_GRADES.map((g) => { const v = row.spreads[g]; const d = row.dod[g]; const dark = v / mx > 0.55;
            return <div key={g} style={{ background: heat(v), border: '1px solid rgba(0,0,0,.04)', borderRadius: 8, padding: '7px 6px 6px', textAlign: 'center' }}>
              <div className="num" style={{ fontFamily: T.font, fontWeight: 700, fontSize: 13.5, color: dark ? '#fff' : T.c900 }}>{v}<span style={{ fontSize: 9.5, fontWeight: 600, opacity: .7 }}>bp</span></div>
              <div className="num" style={{ fontFamily: T.font, fontWeight: 600, fontSize: 9.5, color: dark ? 'rgba(255,255,255,.85)' : d > 0 ? T.up : T.c400 }}>{d > 0 ? '+' : ''}{d}bp</div>
            </div>; })}
        </React.Fragment>)}
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 9 }}>
        <span style={{ width: 5, height: 5, borderRadius: 9, background: T.blue }} />
        <span style={{ fontFamily: T.font, fontWeight: 500, fontSize: 10.5, color: T.c400 }}>보유 포지션이 있는 국가 · 국채 대비 OAS, 전일대비</span>
      </div>
    </div>);
}

// ── ③ DV01 (포지션별 · 넷) ──
function DV01Panel({ pf }) {
  const s = dv01Summary(pf);
  const firm = firmDV01();
  const mx = Math.max(...s.rows.map((r) => r.dv01), 0.001);
  const kpis = [
    { l: 'Gross DV01', v: bfMn(s.gross), sub: '보유 포지션 합', c: T.c900 },
    { l: '선물 헤지', v: bfSigned(s.hedge), sub: '국채선물 매도', c: T.down },
    { l: 'Net DV01', v: bfMn(s.net), sub: '금리 +1bp 시 평가손', c: T.blue },
    { l: '전사 Net DV01', v: bfMn(firm.net), sub: `채권 데스크 전체 (${peopleOf('채권').length}명)`, c: T.c900 },
  ];
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0,.9fr) minmax(0,1.3fr)', gap: 18, alignItems: 'start' }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        {kpis.map((k) =>
          <div key={k.l} style={{ border: '1px solid ' + T.line, borderRadius: 10, padding: '12px 14px', background: T.white }}>
            <div style={{ fontFamily: T.font, fontWeight: 600, fontSize: 11, color: T.c500, textAlign: 'left' }}>{k.l}</div>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginTop: 6 }}>
              <span className="num" style={{ fontFamily: T.font, fontWeight: 800, fontSize: 20, color: k.c, letterSpacing: '-.02em' }}>{k.v}</span>
              <span style={{ fontFamily: T.font, fontWeight: 600, fontSize: 10.5, color: T.c400 }}>백만/bp</span>
            </div>
            <div style={{ fontFamily: T.font, fontWeight: 500, fontSize: 10.5, color: T.c400, marginTop: 4, textAlign: 'left' }}>{k.sub}</div>
          </div>)}
      </div>
      <div>
        <div style={{ fontFamily: T.font, fontWeight: 700, fontSize: 11.5, color: T.c500, marginBottom: 8, textAlign: 'left' }}>포지션별 DV01 <span style={{ fontWeight: 500, color: T.c400 }}>(백만원/bp)</span></div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
          {s.rows.map((r) => (
            <div key={r.id} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <span style={{ width: 128, fontFamily: T.font, fontWeight: 600, fontSize: 12, color: T.c700, textAlign: 'left', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', flex: 'none' }}>{r.name}</span>
              <span className="num" style={{ width: 58, fontFamily: T.font, fontWeight: 500, fontSize: 10.5, color: T.c400, flex: 'none' }}>{r.country} · {r.dur}Y</span>
              <div style={{ flex: 1, height: 9, background: T.c150, borderRadius: 5, overflow: 'hidden' }}>
                <div style={{ width: r.dv01 / mx * 100 + '%', height: '100%', background: COUNTRY_HUE[r.country] || T.blue, borderRadius: 5 }} />
              </div>
              <b className="num" style={{ width: 52, textAlign: 'right', fontFamily: T.font, fontSize: 12.5, color: T.c900, flex: 'none' }}>{bfMn(r.dv01)}</b>
            </div>))}
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, borderTop: '1px dashed ' + T.c250, paddingTop: 7 }}>
            <span style={{ width: 128, fontFamily: T.font, fontWeight: 600, fontSize: 12, color: T.down, textAlign: 'left', flex: 'none' }}>국채선물 매도 헤지</span>
            <span style={{ width: 58, flex: 'none' }} />
            <div style={{ flex: 1 }} />
            <b className="num" style={{ width: 52, textAlign: 'right', fontFamily: T.font, fontSize: 12.5, color: T.down, flex: 'none' }}>{bfSigned(s.hedge)}</b>
          </div>
        </div>
      </div>
    </div>);
}

// ── ④ 기간구조별 DV01 + Greeks ──
function TenorGreeks({ pf }) {
  const tenors = tenorDV01(pf);
  const mx = Math.max(...tenors.map((t) => t.dv01), 0.001);
  const gk = greeksRows(pf);
  const gammaSum = gk.reduce((s, r) => s + r.gamma, 0);
  const vegaSum = gk.reduce((s, r) => s + r.vega, 0);
  const vegaRows = gk.filter((r) => r.vega > 0);
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0,1.1fr) minmax(0,1fr)', gap: 18, alignItems: 'start' }}>
      {/* 기간구조 */}
      <div>
        <div style={{ fontFamily: T.font, fontWeight: 700, fontSize: 11.5, color: T.c500, marginBottom: 10, textAlign: 'left' }}>기간구조별 DV01 <span style={{ fontWeight: 500, color: T.c400 }}>(백만원/bp)</span></div>
        <div style={{ display: 'flex', alignItems: 'flex-end', gap: 12, height: 150, padding: '0 6px' }}>
          {tenors.map((t) => (
            <div key={t.id} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, height: '100%', justifyContent: 'flex-end' }}>
              <span className="num" style={{ fontFamily: T.font, fontWeight: 700, fontSize: 12, color: t.dv01 > 0 ? T.c900 : T.c300 }}>{t.dv01 > 0 ? bfMn(t.dv01) : '—'}</span>
              <div style={{ width: '100%', maxWidth: 64, height: Math.max(3, t.dv01 / mx * 96), background: t.dv01 / mx > 0.66 ? T.blue : t.dv01 > 0 ? '#7FA8D9' : T.c200, borderRadius: '6px 6px 3px 3px', transition: 'height .3s' }} />
              <span style={{ fontFamily: T.font, fontWeight: 600, fontSize: 10.5, color: T.c500, whiteSpace: 'nowrap' }}>{t.label}</span>
              <span style={{ fontFamily: T.font, fontWeight: 500, fontSize: 9.5, color: T.c400, marginTop: -4 }}>{t.n}종목</span>
            </div>))}
        </div>
      </div>
      {/* Greeks */}
      <div>
        <div style={{ fontFamily: T.font, fontWeight: 700, fontSize: 11.5, color: T.c500, marginBottom: 10, textAlign: 'left' }}>Greeks <span style={{ fontWeight: 500, color: T.c400 }}>(감마·베가)</span></div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 10 }}>
          <div style={{ border: '1px solid ' + T.line, borderRadius: 10, padding: '11px 13px', background: T.white }}>
            <div style={{ fontFamily: T.font, fontWeight: 600, fontSize: 10.5, color: T.c500, textAlign: 'left' }}>포트 감마 (Convexity)</div>
            <div className="num" style={{ fontFamily: T.font, fontWeight: 800, fontSize: 19, color: T.c900, marginTop: 5, textAlign: 'left' }}>{bfMn(gammaSum)}<span style={{ fontSize: 10, fontWeight: 600, color: T.c400 }}> 백만/(100bp)²</span></div>
            <div style={{ fontFamily: T.font, fontWeight: 500, fontSize: 10, color: T.c400, marginTop: 3, textAlign: 'left' }}>금리 대변동 시 손익 곡률</div>
          </div>
          <div style={{ border: '1px solid ' + T.line, borderRadius: 10, padding: '11px 13px', background: T.white }}>
            <div style={{ fontFamily: T.font, fontWeight: 600, fontSize: 10.5, color: T.c500, textAlign: 'left' }}>포트 베가 (콜 내재)</div>
            <div className="num" style={{ fontFamily: T.font, fontWeight: 800, fontSize: 19, color: vegaSum > 0 ? T.warn : T.c900, marginTop: 5, textAlign: 'left' }}>{bfMn(vegaSum)}<span style={{ fontSize: 10, fontWeight: 600, color: T.c400 }}> 백만/vol 1%p</span></div>
            <div style={{ fontFamily: T.font, fontWeight: 500, fontSize: 10, color: T.c400, marginTop: 3, textAlign: 'left' }}>콜러블 채권 {vegaRows.length}종목 보유</div>
          </div>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column' }}>
          {gk.slice(0, 5).map((r, i) =>
            <div key={r.id} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6.5px 0', borderBottom: i < 4 ? '1px solid ' + T.c150 : 'none' }}>
              <span style={{ fontFamily: T.font, fontWeight: 600, fontSize: 12, color: T.c700, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', flex: 1, textAlign: 'left' }}>{r.name}</span>
              {r.call && <Pill kind="warn" small>콜러블</Pill>}
              <span className="num" style={{ fontFamily: T.font, fontWeight: 600, fontSize: 11.5, color: T.c600, width: 64, textAlign: 'right' }}>Γ {bfMn(r.gamma)}</span>
              <span className="num" style={{ fontFamily: T.font, fontWeight: 600, fontSize: 11.5, color: r.vega > 0 ? T.warn : T.c300, width: 58, textAlign: 'right' }}>ν {r.vega > 0 ? bfMn(r.vega) : '—'}</span>
            </div>)}
        </div>
      </div>
    </div>);
}

// ── ⑤ 팩터별 리스크 익스포저 (관리 액션 포함) ──
function BondFactorExposure({ pf }) {
  const dec = factorDecompose(pf).filter((d) => d.id !== 'eq');
  return (
    <div>
      <div style={{ display: 'flex', height: 14, borderRadius: 7, overflow: 'hidden', background: T.c150, marginBottom: 6 }}>
        {dec.map((d) => <div key={d.id} style={{ width: d.frac * 100 + '%', background: d.color }} title={d.name} />)}
      </div>
      {dec.map((d, i) =>
        <div key={d.id} style={{ display: 'flex', alignItems: 'center', gap: 9, padding: '9px 0', borderBottom: i < dec.length - 1 ? '1px solid ' + T.c150 : 'none' }}>
          <span style={{ width: 9, height: 9, borderRadius: 3, background: d.color, flex: 'none' }} />
          <span style={{ fontFamily: T.font, fontWeight: 700, fontSize: 12.5, color: T.c800 }}>{d.name}</span>
          <span style={{ fontFamily: T.mono, fontSize: 9.5, color: T.c400 }}>{d.code}</span>
          <span style={{ fontFamily: T.font, fontWeight: 500, fontSize: 10.5, color: T.c500, marginLeft: 6 }}>{d.id !== 'vol' ? <React.Fragment>{d.sensLabel} → <b className="num" style={{ color: d.sensAmt < 0 ? T.down : T.up }}>{fvEok(d.sensAmt)}</b></React.Fragment> : '요인 설명 후 잔차'}</span>
          <span className="num" style={{ marginLeft: 'auto', fontFamily: T.font, fontWeight: 700, fontSize: 13, color: T.c900 }}>{Math.round(d.amt).toLocaleString()}억</span>
          <span className="num" style={{ width: 46, textAlign: 'right', fontFamily: T.font, fontWeight: 600, fontSize: 12, color: T.c500 }}>{(d.frac * 100).toFixed(1)}%</span>
        </div>)}
    </div>);
}

// ── 섹션 조립 (채권 포트폴리오 관리 내) ──
function BondFactorSection({ pf }) {
  return (
    <Card>
      <CardHead title="리스크 요인 분석" sub="이자율·신용·기간구조 민감도를 계량화해 헤지 포인트와 리스크 집중도를 도출" icon="layers" />
      <div style={{ padding: '18px 22px 22px', display: 'flex', flexDirection: 'column', gap: 20 }}>
        <div>
          <div style={{ fontFamily: T.font, fontWeight: 700, fontSize: 12.5, color: T.c700, marginBottom: 10, textAlign: 'left' }}>① 나라별 기준금리</div>
          <PolicyRates />
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0,1.05fr) minmax(0,1fr)', gap: 18, alignItems: 'start' }}>
          <div>
            <div style={{ fontFamily: T.font, fontWeight: 700, fontSize: 12.5, color: T.c700, marginBottom: 10, textAlign: 'left' }}>② 국가 × 등급별 신용스프레드</div>
            <SpreadMatrix pf={pf} />
          </div>
          <div>
            <div style={{ display: 'flex', alignItems: 'center', marginBottom: 10 }}>
              <span style={{ fontFamily: T.font, fontWeight: 700, fontSize: 12.5, color: T.c700 }}>③ 팩터별 리스크 익스포저</span>
            </div>
            <BondFactorExposure pf={pf} />
          </div>
        </div>
        <div>
          <div style={{ fontFamily: T.font, fontWeight: 700, fontSize: 12.5, color: T.c700, marginBottom: 10, textAlign: 'left' }}>④ DV01 — 포지션별 · Net</div>
          <DV01Panel pf={pf} />
        </div>
        <div>
          <div style={{ fontFamily: T.font, fontWeight: 700, fontSize: 12.5, color: T.c700, marginBottom: 10, textAlign: 'left' }}>⑤ 기간구조 · Greeks</div>
          <TenorGreeks pf={pf} />
        </div>
      </div>
    </Card>);
}

// ── 모니터링(채권) 탭용 하이라이트 ──
function BondFactorHighlight({ onMore }) {
  const pf = React.useMemo(() => firmPortfolio('채권'), []);
  const m = summarize(pf);
  const s = dv01Summary(pf);
  const tenors = tenorDV01(pf); const topTenor = tenors.slice().sort((a, b) => b.dv01 - a.dv01)[0];
  const dec = factorDecompose(pf).filter((d) => d.id !== 'eq').slice(0, 2);
  const kr = POLICY_RATES[0]; const us = POLICY_RATES[1];
  const Stat = ({ l, v, u, sub, c }) => (
    <div style={{ flex: 1, minWidth: 0 }}>
      <div style={{ fontFamily: T.font, fontWeight: 600, fontSize: 11, color: T.c500, textAlign: 'left' }}>{l}</div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginTop: 5 }}>
        <span className="num" style={{ fontFamily: T.font, fontWeight: 800, fontSize: 21, color: c || T.c900, letterSpacing: '-.02em' }}>{v}</span>
        <span style={{ fontFamily: T.font, fontWeight: 600, fontSize: 10.5, color: T.c400 }}>{u}</span>
      </div>
      <div style={{ fontFamily: T.font, fontWeight: 500, fontSize: 10.5, color: T.c400, marginTop: 3, textAlign: 'left' }}>{sub}</div>
    </div>);
  return (
    <Card>
      <CardHead title="리스크 요인 하이라이트" sub="트레이딩 데스크 채권 포트폴리오 기준 · 금리/스프레드/Net DV01 요약" icon="layers"
        right={<Btn variant="ghost" size="sm" iconR="chevRight" onClick={onMore}>채권 포트폴리오에서 상세 분석</Btn>} />
      <div style={{ padding: '14px 22px 16px', display: 'flex', alignItems: 'stretch' }}>
        <Stat l="전사 Net DV01" v={bfMn(s.net)} u="백만/bp" sub={`Gross ${bfMn(s.gross)} · Hedge ${bfSigned(s.hedge)}`} c={T.blue} />
        <div style={{ width: 1, background: T.line, margin: '0 18px' }} />
        <Stat l="DV01 최대 만기" v={topTenor.label} u="" sub={`${bfMn(topTenor.dv01)}백만/bp · ${topTenor.n}종목`} />
        <div style={{ width: 1, background: T.line, margin: '0 18px' }} />
        <Stat l="기준금리 (KRW/USD)" v={`${kr.rate.toFixed(2)} / ${us.rate.toFixed(2)}`} u="%" sub={`한국 ${kr.asOfMove} · 미국 ${us.asOfMove}`} />
        <div style={{ width: 1, background: T.line, margin: '0 18px' }} />
        <div style={{ flex: 1.3, minWidth: 0 }}>
          <div style={{ fontFamily: T.font, fontWeight: 600, fontSize: 11, color: T.c500, textAlign: 'left' }}>팩터 기여 Top</div>
          <div style={{ display: 'flex', flexDirection: 'column', marginTop: 4 }}>
            {dec.map((d, i) =>
              <div key={d.id} style={{ display: 'flex', alignItems: 'center', gap: 7, padding: '5px 0', borderBottom: i < dec.length - 1 ? '1px solid ' + T.c150 : 'none' }}>
                <span style={{ width: 8, height: 8, borderRadius: 3, background: d.color, flex: 'none' }} />
                <span style={{ fontFamily: T.font, fontWeight: 700, fontSize: 12, color: T.c800 }}>{d.name}</span>
                <span className="num" style={{ marginLeft: 'auto', fontFamily: T.font, fontWeight: 700, fontSize: 12, color: T.c900 }}>{Math.round(d.amt).toLocaleString()}억 · {(d.frac * 100).toFixed(0)}%</span>
              </div>)}
          </div>
        </div>
      </div>
    </Card>);
}

Object.assign(window, { BondFactorSection, BondFactorHighlight, PolicyRates, SpreadMatrix, DV01Panel, TenorGreeks, BondFactorExposure, bfMn, bfSigned });
