/* ============================================================
   pages_calc.jsx — 成本核算结果（对齐科伦测算成本表）/ 公式口径
   ============================================================ */
const { Ico, Btn, Tag, Chip, Card, CardHead, Switch, Avatar, Drawer, Modal, Empty, Bar, Ring, StackBar, Spark, Donut, Lines, Columns, ColumnsCompare, RankBars, useApp, FlowStepper, MiniSteps, Timeline, SrcDot, DiffTable, CompletenessPanel } = window;

const { useState, useMemo, useEffect, Fragment } = React;
const yuanC = (v) => (v == null ? '—' : Number(v).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }));
const wanC = (v) => (Math.abs(v) >= 10000 ? (v / 10000).toFixed(2) + ' 万' : Math.round(v).toLocaleString());
const numF = (v) => (v == null ? '—' : Number(v).toLocaleString('zh-CN'));
const CAP_C = { material: 'var(--c-material)', labor: 'var(--c-labor)', overhead: 'var(--c-overhead)' };
const pct = (v) => Math.round(Number(v) * 1000) / 10 + '%';

/* ================================================================
   1. 成本核算结果（科伦《测算成本》/《最小单位测算成本》/《成本明细》）
   ================================================================ */
function ForecastPage() {
  const app = useApp();
  const { calc, COMPLETENESS, activeMode, setActiveMode, go, role, toast, sync, decls } = app;
  const sel = activeMode;
  const [tab, setTab] = useState('penetrate');

  const modes = window.MODES;
  const cur = calc[sel];
  const curMode = window.modeById(sel);
  const openDiffs = sync.diffs.filter((d) => d.status === 'open');

  const boxNoTax = modes.map((m) => calc[m.key].minUnit.box.noTax);
  const minBox = Math.min.apply(null, boxNoTax);
  const maxBox = Math.max.apply(null, boxNoTax);
  const tentTotal = cur.prodCost.tentTax;
  const tentDelta = cur.prodCost.tax ? (tentTotal - cur.prodCost.tax) / cur.prodCost.tax * 100 : 0;

  const approvedD = decls.find((x) => x.status === 'approved');
  const reviewingD = decls.find((x) => x.status === 'reviewing');
  const locked = !!(approvedD && approvedD.lockedAt);

  /* 恒等式：成本明细合计（除临测对照列）= 测算生产成本（不含税） */
  const detailSum = cur.detail.filter((x) => x.k !== '临测物料成本').reduce((s, x) => s + x.v, 0);

  return (
    <div className="scroll tight" data-screen-label="08 成本核算结果">
      <div style={{ padding: '18px 18px 0' }}>
        <div className="sec-title">
          <h2>成本核算结果</h2>
          <span className="sub">对齐科伦《测算成本 / 最小单位测算成本 / 成本明细》· 含税与不含税双口径 · 每个数字可追溯到来源</span>
          <div className="right">
            <div className="seg">
              {['Q4', 'Q3'].map((q) => <button key={q} className={q === 'Q4' ? 'on' : ''}>{q}</button>)}
            </div>
            {role === 'finance' && <Btn size="sm" kind="primary" icon="refresh" onClick={() => toast('已按 9 条公式口径全量重算 6 个工况', 'ok')}>全量重算</Btn>}
            <Btn size="sm" icon="download">导出测算表</Btn>
          </div>
        </div>

        {openDiffs.length > 0 && (
          <div className="notice warn mb12">
            <span className="n-ico"><Ico name="alert" size={15} /></span>
            <div>
              存在 <b>{openDiffs.length} 项</b>未确认的物料价格差异（{openDiffs.map((d) => d.mid).join('、')}）。
              为保证口径一致，<b>未确认前按本地值核算</b>，差异确认后自动重算。
              <span className="linkish" onClick={() => go('sync')}> 去处理差异 →</span>
            </div>
          </div>
        )}

        {/* 汇总 */}
        <div className="grid g4 mb12">
          <Card><div className="kpi">
            <div className="k-label">{sel} 测算生产成本（含税）</div>
            <div className="k-value">{wanC(cur.prodCost.tax)}<small>元</small></div>
            <div className="k-foot"><span className="muted">不含税 {wanC(cur.prodCost.noTax)} 元 · 当前工况</span></div>
          </div></Card>
          <Card><div className="kpi">
            <div className="k-label">最小单位成本区间（元/盒）</div>
            <div className="k-value" style={{ fontSize: 24 }}>{yuanC(minBox)} ~ {yuanC(maxBox)}</div>
            <div className="k-foot"><span className="muted">不含税 · 模式6 规模效应最低</span></div>
          </div></Card>
          <Card><div className="kpi">
            <div className="k-label">{sel} 临测价格口径</div>
            <div className="k-value" style={{ color: tentDelta > 0 ? 'var(--warn)' : 'var(--ink)' }}>{wanC(tentTotal)}<small>元</small></div>
            <div className="k-foot">
              <span className={'delta ' + (tentDelta > 0 ? 'up' : 'down')}><Ico name={tentDelta > 0 ? 'arrowUp' : 'arrowDown'} size={11} />{Math.abs(tentDelta).toFixed(1)}%</span>
              较正式价格口径
            </div>
          </div></Card>
          <Card><div className="kpi">
            <div className="k-label">审核锁定</div>
            <div className="k-value" style={{ fontSize: 20, letterSpacing: 0, marginTop: 12, color: locked ? 'var(--ok)' : 'var(--warn)' }}>
              <Ico name="lock" size={16} /> {locked ? 'Q3 基线已锁定' : '待审批锁定'}
            </div>
            <div className="k-foot"><span className="muted">{approvedD ? approvedD.id + ' · ' + approvedD.lockedAt : reviewingD ? reviewingD.id + ' 待财务审批' : '—'}</span></div>
          </div></Card>
        </div>

        <div className="grid" style={{ gridTemplateColumns: 'minmax(0,296px) minmax(0,1fr)', alignItems: 'start' }}>
          {/* 左：工况列表 */}
          <div className="col" style={{ gap: 12 }}>
            {modes.map((m) => {
              const c = calc[m.key];
              const items = COMPLETENESS[m.key] || [];
              const ok = items.filter((x) => x.ok).length;
              const ws = c.factors.wsCash.tax + c.factors.wsDepr.tax;
              const ax = c.factors.auxCash.tax + c.factors.auxDepr.tax;
              return (
                <Card key={m.key} style={sel === m.key ? { boxShadow: '0 0 0 2px var(--primary-line), var(--sh-card)' } : null}>
                  <button style={{ width: '100%', textAlign: 'left', padding: '13px 15px' }} onClick={() => setActiveMode(m.key)}>
                    <div className="row" style={{ gap: 8 }}>
                      <span className="num" style={{ fontSize: 12.5, fontWeight: 600 }}>{m.key} {m.name}</span>
                      <span className="spacer" />
                      {ok === items.length ? <Tag kind="ok" dot>已齐备</Tag> : <Tag kind="warn" dot>暂定</Tag>}
                    </div>
                    <div className="tiny muted" style={{ marginTop: 3 }}>{m.desc} · {m.kind} · {m.batches} 批 × {m.hpd}h/天</div>
                    <div className="row" style={{ gap: 10, marginTop: 10, alignItems: 'flex-end' }}>
                      <div>
                        <div className="tiny muted">最小单位成本（元/盒·含税）</div>
                        <div className="num" style={{ fontSize: 19, fontWeight: 600, letterSpacing: '-0.5px' }}>{yuanC(c.minUnit.box.tax)}</div>
                      </div>
                      <span className="spacer" />
                      <div style={{ textAlign: 'right' }}>
                        <div className="tiny muted">测算生产成本（含税）</div>
                        <div className="num" style={{ fontSize: 13, fontWeight: 500 }}>{wanC(c.prodCost.tax)} 元</div>
                      </div>
                    </div>
                    <div style={{ marginTop: 11 }}><StackBar parts={[
                      { value: c.material.tax.total, color: CAP_C.material },
                      { value: ws, color: CAP_C.labor },
                      { value: ax, color: CAP_C.overhead },
                    ]} height={7} /></div>
                    <div className="row tiny muted" style={{ gap: 10, marginTop: 6 }}>
                      <span><i className="legend" style={{ background: CAP_C.material }} />物料</span>
                      <span><i className="legend" style={{ background: CAP_C.labor }} />车间</span>
                      <span><i className="legend" style={{ background: CAP_C.overhead }} />辅助</span>
                    </div>
                  </button>
                </Card>
              );
            })}
            <div className="notice flat">
              <span className="n-ico"><Ico name="info" size={14} /></span>
              <div className="tiny">元/盒 = 测算生产成本 ÷ 产成品标准成品量；元/片按最小单位系数 {window.PRODUCT.minUnitFactor} 换算。切换工况查看测算成本、最小单位成本与成本明细。</div>
            </div>
          </div>

          {/* 右：详情 */}
          <div className="col" style={{ gap: 12 }}>
            <Card>
              <CardHead title={curMode.name + ' · 测算结果'} sub={curMode.desc + ' · ' + curMode.kind + ' · 半成品→产成品（' + window.PRODUCT.name + ' ' + window.PRODUCT.spec + '）'}
                right={<Fragment>
                  <Tag kind={COMPLETENESS[sel].every((x) => x.ok) ? 'ok' : 'warn'} dot>{COMPLETENESS[sel].every((x) => x.ok) ? '数据齐备' : '暂定'}</Tag>
                  <Btn size="sm" icon="sigma" onClick={() => go('formula')}>查看公式口径</Btn>
                </Fragment>} />
              <div className="card-head plain" style={{ borderBottom: '1px solid var(--line)' }}>
                <div className="seg">
                  {[['penetrate', '测算生产成本'], ['minUnit', '最小单位测算成本'], ['detail', '成本明细'], ['source', '数据来源']].map(([k, l]) => (
                    <button key={k} className={tab === k ? 'on' : ''} onClick={() => setTab(k)}>{l}</button>
                  ))}
                </div>
              </div>

              {tab === 'penetrate' && (
                <div>
                  <div className="tbl-wrap">
                    <table className="tbl">
                      <thead>
                        <tr>
                          <th>成本项（科伦口径）</th>
                          <th className="r" style={{ width: 128 }}>含税</th>
                          <th className="r" style={{ width: 128 }}>不含税</th>
                          <th style={{ width: 190 }}>数据来源</th>
                        </tr>
                      </thead>
                      <tbody>
                        <tr>
                          <td>
                            <div className="primary-cell">物料成本</div>
                            <div className="sub-cell">Σ 物料单耗 × 成品量 × 采购单价 · {cur.material.tax.lines.length} 行 BOM 明细</div>
                          </td>
                          <td className="r num">{yuanC(cur.material.tax.total)}</td>
                          <td className="r num">{yuanC(cur.material.noTax.total)}</td>
                          <td>
                            <div className="col" style={{ gap: 3 }}>
                              <span className="srcline"><SrcDot src="bom" />BOM 单耗</span>
                              <span className="srcline"><SrcDot src="supply" />物料价格（供应部）</span>
                              <span className="srcline"><SrcDot src="calc" />公式计算</span>
                            </div>
                          </td>
                        </tr>
                        <tr>
                          <td>
                            <div className="primary-cell">车间付现</div>
                            <div className="sub-cell">KL01 水 / KL02 电 / KL03 汽 / KL04 人工 / KL06 物料消耗 × 车间报工单价</div>
                          </td>
                          <td className="r num">{yuanC(cur.factors.wsCash.tax)}</td>
                          <td className="r num">{yuanC(cur.factors.wsCash.noTax)}</td>
                          <td>
                            <div className="col" style={{ gap: 3 }}>
                              <span className="srcline"><SrcDot src="apply" />车间报工量</span>
                              <span className="srcline"><SrcDot src="finance" />车间报工单价</span>
                            </div>
                          </td>
                        </tr>
                        <tr>
                          <td>
                            <div className="primary-cell">车间折旧</div>
                            <div className="sub-cell">KL05 折旧：生产时长 {cur.factors.hours} h × 车间折旧单价</div>
                          </td>
                          <td className="r num">{yuanC(cur.factors.wsDepr.tax)}</td>
                          <td className="r num">{yuanC(cur.factors.wsDepr.noTax)}</td>
                          <td>
                            <div className="col" style={{ gap: 3 }}>
                              <span className="srcline"><SrcDot src="apply" />生产时长</span>
                              <span className="srcline"><SrcDot src="finance" />车间折旧单价</span>
                            </div>
                          </td>
                        </tr>
                        <tr>
                          <td>
                            <div className="primary-cell">辅助付现</div>
                            <div className="sub-cell">辅助口径：基地公用工程等辅助部门 × 辅助报工单价</div>
                          </td>
                          <td className="r num">{yuanC(cur.factors.auxCash.tax)}</td>
                          <td className="r num">{yuanC(cur.factors.auxCash.noTax)}</td>
                          <td>
                            <div className="col" style={{ gap: 3 }}>
                              <span className="srcline"><SrcDot src="apply" />车间报工量</span>
                              <span className="srcline"><SrcDot src="finance" />辅助报工单价</span>
                            </div>
                          </td>
                        </tr>
                        <tr>
                          <td>
                            <div className="primary-cell">辅助折旧</div>
                            <div className="sub-cell">辅助部门折旧：生产时长 {cur.factors.hours} h × 辅助折旧单价</div>
                          </td>
                          <td className="r num">{yuanC(cur.factors.auxDepr.tax)}</td>
                          <td className="r num">{yuanC(cur.factors.auxDepr.noTax)}</td>
                          <td>
                            <div className="col" style={{ gap: 3 }}>
                              <span className="srcline"><SrcDot src="apply" />生产时长</span>
                              <span className="srcline"><SrcDot src="finance" />辅助折旧单价</span>
                            </div>
                          </td>
                        </tr>
                        <tr className="totals">
                          <td>测算生产成本 = 物料 + 车间付现 + 车间折旧 + 辅助付现 + 辅助折旧</td>
                          <td className="r num" style={{ fontSize: 14 }}>{yuanC(cur.prodCost.tax)}</td>
                          <td className="r num" style={{ fontSize: 14 }}>{yuanC(cur.prodCost.noTax)}</td>
                          <td><span className="srcline"><SrcDot src="calc" />公式计算</span></td>
                        </tr>
                        <tr style={{ background: 'var(--warn-soft)' }}>
                          <td>
                            <div className="primary-cell" style={{ color: 'var(--warn-deep, #8a5a00)' }}>临测价格生产成本（对照）</div>
                            <div className="sub-cell">物料按临测价双轨测算，不计入正式口径</div>
                          </td>
                          <td className="r num" style={{ color: 'var(--warn-deep, #8a5a00)' }}>{yuanC(cur.prodCost.tentTax)}</td>
                          <td className="r num" style={{ color: 'var(--warn-deep, #8a5a00)' }}>{yuanC(cur.prodCost.tentNoTax)}</td>
                          <td><span className="srcline"><SrcDot src="supply" />临测价（供应部）</span></td>
                        </tr>
                      </tbody>
                    </table>
                  </div>

                  <div style={{ padding: '12px 14px' }}>
                    <div className="tiny muted mb8" style={{ fontWeight: 500 }}>费用报工明细（KL01-KL06 · 报工量 × 车间/辅助单价）</div>
                    <div className="tbl-wrap">
                      <table className="tbl">
                        <thead>
                          <tr>
                            <th style={{ width: 130 }}>报工项</th>
                            <th className="r" style={{ width: 110 }}>报工量</th>
                            <th className="r" style={{ width: 110 }}>车间单价</th>
                            <th className="r" style={{ width: 110 }}>辅助单价</th>
                            <th className="r" style={{ width: 120 }}>车间成本（含税）</th>
                            <th className="r" style={{ width: 120 }}>辅助成本（含税）</th>
                          </tr>
                        </thead>
                        <tbody>
                          {cur.factors.lines.map((l) => (
                            <tr key={l.code}>
                              <td>
                                <div className="primary-cell">{l.name}</div>
                                <div className="sub-cell num">{l.code} · {l.cat}{l.kind === 'depr' ? ' · 折旧' : ''}</div>
                              </td>
                              <td className="r num">{numF(l.qty)} {l.unit}</td>
                              <td className="r num">{l.wsPrice}</td>
                              <td className="r num">{l.auxPrice}</td>
                              <td className="r num">{yuanC(l.wsTax)}</td>
                              <td className="r num">{yuanC(l.auxTax)}</td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  </div>
                </div>
              )}

              {tab === 'minUnit' && (
                <div className="card-body">
                  <div className="dsec">
                    <h4>{curMode.name} · 最小单位测算成本 <span className="line" /></h4>
                    <div className="grid g2 mb12">
                      {[
                        ['元/片（含税）', yuanC(cur.minUnit.piece.tax)],
                        ['元/片（不含税）', yuanC(cur.minUnit.piece.noTax)],
                        ['元/盒（含税）', yuanC(cur.minUnit.box.tax)],
                        ['元/盒（不含税）', yuanC(cur.minUnit.box.noTax)],
                      ].map(([k, v]) => (
                        <div key={k} style={{ border: '1px solid var(--line)', borderRadius: 8, padding: '10px 12px', background: 'var(--surface)' }}>
                          <div className="tiny muted">{k}</div>
                          <div className="num" style={{ fontSize: 18, fontWeight: 600, marginTop: 3 }}>{v}</div>
                        </div>
                      ))}
                    </div>
                    <div className="tiny muted mb8">
                      口径：测算生产成本（不含税）÷ 折算片数 × 最小单位系数 {window.PRODUCT.minUnitFactor}
                      即 {yuanC(cur.prodCost.noTax)} ÷ {numF(cur.std.fin.std * window.PRODUCT.minUnitFactor)} 片 = {yuanC(cur.minUnit.piece.noTax)} 元/片　× {window.PRODUCT.minUnitFactor} = {yuanC(cur.minUnit.box.noTax)} 元/盒
                    </div>
                  </div>

                  <div className="dsec">
                    <h4>6 工况对比（规模效应） <span className="line" /></h4>
                    <div className="tbl-wrap" style={{ margin: '-4px -16px 0' }}>
                      <table className="tbl">
                        <thead>
                          <tr>
                            <th>工况</th>
                            <th className="r">产成品（盒）</th>
                            <th className="r">折算片数</th>
                            <th className="r">元/片<br /><span className="tiny">不含税</span></th>
                            <th className="r">元/盒<br /><span className="tiny">不含税</span></th>
                            <th className="r">元/盒<br /><span className="tiny">含税</span></th>
                            <th className="r">元/盒<br /><span className="tiny">临测含税</span></th>
                          </tr>
                        </thead>
                        <tbody>
                          {modes.map((m) => {
                            const c = calc[m.key];
                            const isMin = c.minUnit.box.noTax === minBox;
                            return (
                              <tr key={m.key} style={isMin ? { background: 'var(--primary-soft)' } : null}>
                                <td>
                                  <div className="primary-cell">{m.key} {m.name}</div>
                                  <div className="sub-cell">{m.desc}</div>
                                </td>
                                <td className="r num">{numF(c.std.fin.std)}</td>
                                <td className="r num">{numF(c.std.fin.std * window.PRODUCT.minUnitFactor)}</td>
                                <td className="r num">{yuanC(c.minUnit.piece.noTax)}</td>
                                <td className="r num" style={{ fontWeight: isMin ? 700 : 500, color: isMin ? 'var(--primary)' : 'var(--ink)' }}>
                                  {yuanC(c.minUnit.box.noTax)}{isMin && <Ico name="arrowDown" size={11} style={{ verticalAlign: 0, marginLeft: 4 }} />}
                                </td>
                                <td className="r num">{yuanC(c.minUnit.box.tax)}</td>
                                <td className="r num" style={{ color: 'var(--ink-2)' }}>{yuanC(c.minUnit.box.tentTax)}</td>
                              </tr>
                            );
                          })}
                        </tbody>
                      </table>
                    </div>
                  </div>
                </div>
              )}

              {tab === 'detail' && (
                <div>
                  <div className="tbl-wrap">
                    <table className="tbl">
                      <thead>
                        <tr>
                          <th>成本明细项（不含税）</th>
                          <th className="r" style={{ width: 150 }}>金额</th>
                          <th style={{ width: 130 }}>来源</th>
                        </tr>
                      </thead>
                      <tbody>
                        {cur.detail.map((x) => {
                          const isTent = x.k === '临测物料成本';
                          return (
                            <tr key={x.k} style={isTent ? { background: 'var(--warn-soft)' } : null}>
                              <td>
                                <span className="primary-cell" style={isTent ? { color: 'var(--warn-deep, #8a5a00)' } : null}>{x.k}</span>
                                {isTent && <span className="tiny muted">（双轨对照列 · 不计入合计）</span>}
                              </td>
                              <td className="r num">{yuanC(x.v)}</td>
                              <td><span className="srcline"><SrcDot src={x.src} />{window.SRC_META[x.src].label}</span></td>
                            </tr>
                          );
                        })}
                        <tr className="totals">
                          <td>合计（不含临测对照列）</td>
                          <td className="r num" style={{ fontSize: 14 }}>{yuanC(detailSum)}</td>
                          <td><span className="srcline"><SrcDot src="calc" />公式计算</span></td>
                        </tr>
                      </tbody>
                    </table>
                  </div>
                  <div style={{ padding: '12px 14px' }}>
                    <div className="notice ok">
                      <span className="n-ico"><Ico name="checkc" size={13} /></span>
                      <div className="tiny">恒等式校验通过：成本明细合计 {yuanC(detailSum)} 元 ＝ 测算生产成本（不含税）{yuanC(cur.prodCost.noTax)} 元。</div>
                    </div>
                    {locked && approvedD ? (
                      <div className="notice ok mt12">
                        <span className="n-ico"><Ico name="lock" size={13} /></span>
                        <div className="tiny">成本明细已审核锁定：{approvedD.id}（{approvedD.period} 基线）· 审核人 {approvedD.lockBy} · 审核时间 {approvedD.lockedAt}。锁定后不可修改。</div>
                      </div>
                    ) : (
                      <div className="notice warn mt12">
                        <span className="n-ico"><Ico name="alert" size={13} /></span>
                        <div className="tiny">{reviewingD ? reviewingD.id + ' 待财务审批，通过后成本明细将审核锁定并记录审核时间。' : '本期尚未有已锁定的成本明细版本。'}</div>
                      </div>
                    )}
                  </div>
                </div>
              )}

              {tab === 'source' && (
                <div className="card-body">
                  <div className="dsec">
                    <h4>参与计算的字段与来源 <span className="line" /></h4>
                    <div className="tbl-wrap" style={{ margin: '-4px -16px 0' }}>
                      <table className="tbl">
                        <thead><tr><th>字段</th><th style={{ width: 110 }} className="r">单位</th><th style={{ width: 170 }}>来源</th></tr></thead>
                        <tbody>
                          {window.FIELDS.map((f) => (
                            <tr key={f.id}>
                              <td className="primary-cell">{f.id}</td>
                              <td className="r num tiny">{f.unit}</td>
                              <td><span className="srcline"><SrcDot src={f.src} />{window.SRC_META[f.src].label}</span></td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  </div>
                  <div className="notice flat">
                    <span className="n-ico"><Ico name="info" size={14} /></span>
                    <div className="tiny">来源口径：车间填报（新都附表1）· 供应部（物料价格表）· 财务录入（报工单价）· 中台/BOM 主数据 · 公式计算（科伦口径 9 条公式）。</div>
                  </div>
                </div>
              )}
            </Card>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ================================================================
   2. 公式口径（科伦表字段来源 · 9 条）
   ================================================================ */
const F_INVOLVE = {
  stdQty: { fields: [['批理论产量', 'apply'], ['成品率', 'apply'], ['抽留样', 'apply'], ['抽样次数', 'apply'], ['连续生产批次', 'apply']], unit: '片/盒' },
  material: { fields: [['物料单耗', 'bom'], ['标准成品量', 'calc'], ['含税采购单价', 'supply'], ['发票税率', 'supply']], unit: '元' },
  wsCash: { fields: [['报工量', 'apply'], ['车间报工单价', 'finance']], unit: '元' },
  wsDepr: { fields: [['生产时长', 'apply'], ['车间报工单价', 'finance']], unit: '元' },
  auxCash: { fields: [['报工量', 'apply'], ['辅助报工单价', 'finance']], unit: '元' },
  auxDepr: { fields: [['生产时长', 'apply'], ['辅助报工单价', 'finance']], unit: '元' },
  prodCost: { fields: [['物料成本', 'calc'], ['车间付现', 'calc'], ['车间折旧', 'calc'], ['辅助付现', 'calc'], ['辅助折旧', 'calc']], unit: '元' },
  minUnit: { fields: [['测算生产成本', 'calc'], ['标准成品量', 'calc'], ['最小单位系数', 'mdm']], unit: '元/最小单位' },
  tentative: { fields: [['临测物料成本', 'calc'], ['车间付现', 'calc'], ['车间折旧', 'calc'], ['辅助付现', 'calc'], ['辅助折旧', 'calc']], unit: '元' },
};

/* 代入样例（以选中工况实时值展开公式） */
function formulaExample(id, c, m) {
  switch (id) {
    case 'stdQty':
      return {
        main: numF(c.std.fin.std) + ' 盒（半成品 ' + numF(c.std.semi.std) + ' 片）',
        sub: '产成品：（' + m.stages.fin.batchQty + ' × ' + pct(m.stages.fin.yield) + ' − ' + (m.stages.fin.sample || 0) + ' × ' + m.stages.fin.sampleTimes + '）× ' + m.batches + ' 批 = ' + numF(c.std.fin.std) + ' 盒',
        sub2: '半成品：' + m.stages.semi.batchQty + ' × ' + pct(m.stages.semi.yield) + ' × ' + m.batches + ' 批 = ' + numF(c.std.semi.std) + ' 片（无抽留样）',
      };
    case 'material': {
      const l0 = c.material.tax.lines[0];
      return {
        main: yuanC(c.material.tax.total) + '（不含税 ' + yuanC(c.material.noTax.total) + '）',
        sub: 'Σ ' + c.material.tax.lines.length + ' 行 BOM 明细：单耗 × 成品量 × 采购单价',
        sub2: '例 原料药：200 g/万片 × ' + (c.std.semi.std / 10000).toFixed(4) + ' 万片 × 42.00 元/g = ' + yuanC(l0.costTax) + ' 元',
      };
    }
    case 'wsCash': {
      const l1 = c.factors.lines.find((x) => x.code === 'KL01');
      return {
        main: yuanC(c.factors.wsCash.tax) + '（不含税 ' + yuanC(c.factors.wsCash.noTax) + '）',
        sub: 'Σ 报工量 × 车间报工单价（KL01 水 / KL02 电 / KL03 汽 / KL04 人工 / KL06 物料消耗）',
        sub2: '例 水：' + numF(l1.qty) + ' 吨 × ' + l1.wsPrice + ' 元 = ' + yuanC(l1.wsTax) + ' 元',
      };
    }
    case 'wsDepr':
      return {
        main: yuanC(c.factors.wsDepr.tax) + '（不含税 ' + yuanC(c.factors.wsDepr.noTax) + '）',
        sub: 'KL05 折旧报工量（生产时长）× 车间折旧单价',
        sub2: c.factors.hours + ' h × 180 元/h = ' + yuanC(c.factors.wsDepr.tax) + ' 元',
      };
    case 'auxCash': {
      const l1 = c.factors.lines.find((x) => x.code === 'KL01');
      return {
        main: yuanC(c.factors.auxCash.tax) + '（不含税 ' + yuanC(c.factors.auxCash.noTax) + '）',
        sub: 'Σ 报工量 × 辅助报工单价（基地公用工程等辅助部门）',
        sub2: '例 水：' + numF(l1.qty) + ' 吨 × ' + l1.auxPrice + ' 元 = ' + yuanC(l1.auxTax) + ' 元',
      };
    }
    case 'auxDepr':
      return {
        main: yuanC(c.factors.auxDepr.tax) + '（不含税 ' + yuanC(c.factors.auxDepr.noTax) + '）',
        sub: '辅助部门折旧报工量（生产时长）× 辅助折旧单价',
        sub2: c.factors.hours + ' h × 45 元/h = ' + yuanC(c.factors.auxDepr.tax) + ' 元',
      };
    case 'prodCost':
      return {
        main: yuanC(c.prodCost.tax) + '（不含税 ' + yuanC(c.prodCost.noTax) + '）',
        sub: '物料成本 + 车间付现 + 车间折旧 + 辅助付现 + 辅助折旧',
        sub2: yuanC(c.material.tax.total) + ' + ' + yuanC(c.factors.wsCash.tax) + ' + ' + yuanC(c.factors.wsDepr.tax) + ' + ' + yuanC(c.factors.auxCash.tax) + ' + ' + yuanC(c.factors.auxDepr.tax) + ' = ' + yuanC(c.prodCost.tax) + ' 元',
      };
    case 'minUnit':
      return {
        main: Number(c.minUnit.piece.noTax).toFixed(4) + ' 元/片 → ' + yuanC(c.minUnit.box.noTax) + ' 元/盒',
        sub: '测算生产成本（不含税）÷ 折算片数 × 最小单位系数',
        sub2: yuanC(c.prodCost.noTax) + ' ÷ ' + numF(c.std.fin.std * window.PRODUCT.minUnitFactor) + ' 片 = ' + Number(c.minUnit.piece.noTax).toFixed(4) + ' 元/片　× ' + window.PRODUCT.minUnitFactor + ' = ' + yuanC(c.minUnit.box.noTax) + ' 元/盒',
      };
    case 'tentative':
      return {
        main: yuanC(c.prodCost.tentTax) + '（临测口径 · 含税）',
        sub: '临测物料成本 + 车间付现 + 车间折旧 + 辅助付现 + 辅助折旧',
        sub2: yuanC(c.material.tentTax.total) + ' + ' + yuanC(c.factors.wsCash.tax) + ' + ' + yuanC(c.factors.wsDepr.tax) + ' + ' + yuanC(c.factors.auxCash.tax) + ' + ' + yuanC(c.factors.auxDepr.tax) + ' = ' + yuanC(c.prodCost.tentTax) + ' 元',
      };
    default:
      return { main: '—', sub: '', sub2: '' };
  }
}

function FormulaPage() {
  const app = useApp();
  const { calc } = app;
  const [selId, setSelId] = useState('stdQty');
  const [sample, setSample] = useState('M1');

  const sel = window.FORMULAS.find((f) => f.id === selId);
  const c = calc[sample];
  const m = window.modeById(sample);
  const ex = formulaExample(selId, c, m);
  const inv = F_INVOLVE[selId];

  return (
    <div className="scroll tight" data-screen-label="09 公式口径">
      <div style={{ padding: '18px 18px 0' }}>
        <div className="sec-title">
          <h2>公式口径</h2>
          <span className="sub">对齐科伦表字段来源标注 · 9 条公式口径 · 财务规则只读</span>
          <div className="right">
            <span className="tag" style={{ height: 24 }}>口径 v1.0 · 2026-09-01 生效</span>
          </div>
        </div>
      </div>

      <div style={{ padding: '0 18px 18px' }}>
        <div className="grid" style={{ gridTemplateColumns: 'minmax(0,1.3fr) minmax(0,1fr)', alignItems: 'start' }}>
          {/* 左：公式清单 */}
          <div className="col" style={{ gap: 12 }}>
            <Card>
              <CardHead title="成本字段与公式口径" sub="按计算顺序排列 · 标准成品量与物料成本由结构聚合，锁定不可改"
                right={<div className="row" style={{ gap: 6 }}>
                  <span className="tiny muted">代入样例工况</span>
                  <select className="select" style={{ height: 26, width: 130, fontSize: 12 }} value={sample} onChange={(e) => setSample(e.target.value)}>
                    {window.MODES.map((mm) => <option key={mm.key} value={mm.key}>{mm.key} {mm.name}</option>)}
                  </select>
                </div>} />
              <div className="card-body">
                {window.FORMULAS.map((f, idx) => {
                  const isSel = f.id === selId;
                  const val = formulaExample(f.id, c, m).main;
                  return (
                    <div key={f.id} className={'formula-row' + (isSel ? ' sel' : '')}>
                      <div className="fr-head" onClick={() => setSelId(f.id)}>
                        <span className="num tiny muted" style={{ width: 16 }}>{idx + 1}</span>
                        <span className="fr-name">{f.name}</span>
                        {f.locked && <Tag><Ico name="lock" size={10} />锁定</Tag>}
                        <span className="fr-eq nowrap" style={{ overflow: 'hidden', textOverflow: 'ellipsis', flex: 1, minWidth: 0 }}>{f.expr}</span>
                        <span className="fr-val">{val}</span>
                        <Ico name={isSel ? 'up' : 'down'} size={14} style={{ color: 'var(--ink-4)' }} />
                      </div>

                      {isSel && (
                        <div className="formula-body">
                          <div className="row" style={{ gap: 8, marginBottom: 10 }}>
                            <span className="tiny muted" style={{ flex: 1 }}>
                              {f.locked ? '该字段由 BOM / 生产数据结构聚合，口径锁定，不可编辑。' : '口径说明与公式结构由财务部维护，改动需走公式变更审批并留痕。'}
                            </span>
                          </div>

                          <div className="fr-tokens" style={{ marginBottom: 10 }}>
                            <span className="mono" style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--ink-2)' }}>{f.name} ＝</span>
                            <span className="tok field" style={{ fontSize: 12.5 }}>{f.expr}</span>
                          </div>

                          <div className="tiny muted mb8">涉及字段（来源标注）</div>
                          <div className="palette" style={{ marginBottom: 10 }}>
                            {inv.fields.map(([id2, src]) => (
                              <span className="pal-item" key={id2} style={{ cursor: 'default' }}>
                                <SrcDot src={src} />{id2}<span className="tiny muted">{window.SRC_META[src].label}</span>
                              </span>
                            ))}
                          </div>

                          <div className="field">
                            <label>口径说明</label>
                            <div className="tiny" style={{ lineHeight: 1.7, padding: '8px 10px', border: '1px solid var(--line)', borderRadius: 8, background: 'var(--surface)' }}>{f.note}</div>
                          </div>
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            </Card>
          </div>

          {/* 右：代入试算 + 口径总览 */}
          <div className="col" style={{ gap: 12 }}>
            <Card>
              <CardHead title="代入试算" sub={m.key + ' ' + m.name + ' · ' + m.desc}
                right={<Tag kind="ok" dot>与口径一致</Tag>} />
              <div className="card-body">
                <div className="preview-panel">
                  <div className="pv-row" style={{ background: 'var(--primary-soft)', margin: '0 -13px', padding: '7px 13px', borderRadius: 6 }}>
                    <span style={{ width: 130, fontWeight: 600, fontSize: 12.5 }}>{sel.name}</span>
                    <span className="spacer" />
                    <span style={{ fontWeight: 600, fontSize: 13 }}>{ex.main}</span>
                  </div>
                  <div className="pv-row">
                    <span style={{ width: 130, fontSize: 12.5 }}>计算口径</span>
                    <span className="tiny muted" style={{ flex: 1 }}>{ex.sub}</span>
                  </div>
                  {ex.sub2 && (
                    <div className="pv-row">
                      <span style={{ width: 130, fontSize: 12.5 }}>代入展开</span>
                      <span className="tiny mono" style={{ flex: 1 }}>{ex.sub2}</span>
                    </div>
                  )}
                  <div className="pv-row">
                    <span style={{ width: 130, fontSize: 12.5 }}>结果单位</span>
                    <span className="tiny muted" style={{ flex: 1 }}>{F_INVOLVE[selId].unit}</span>
                  </div>
                </div>

                <div className="notice flat mt12">
                  <span className="n-ico"><Ico name="info" size={14} /></span>
                  <div className="tiny">
                    试算基于样例工况 <b>{m.key}</b> 的当前主数据与车间填报值。口径修改需经财务审批并在审计日志留痕；已锁定版本的测算结果不受后续口径变更回溯影响。
                  </div>
                </div>
              </div>
            </Card>

            <Card>
              <CardHead title="口径总览" sub={window.FORMULAS.length + ' 条 · 字段来源' + Object.keys(window.SRC_META).length + ' 类'} />
              <div className="card-body" style={{ paddingTop: 6 }}>
                <div className="tbl-wrap">
                  <table className="tbl">
                    <thead><tr><th>来源</th><th style={{ width: 90 }} className="c">标识</th></tr></thead>
                    <tbody>
                      {Object.keys(window.SRC_META).map((k) => (
                        <tr key={k}>
                          <td className="primary-cell">{window.SRC_META[k].label}</td>
                          <td className="c"><span className="srcline"><SrcDot src={k} />{window.SRC_META[k].dot}</span></td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
                <div className="notice flat mt8">
                  <span className="n-ico"><Ico name="lock" size={13} /></span>
                  <div className="tiny">公式口径为财务规则，普通角色只读；如需调整请联系财务部管理员并走版本发布流程。</div>
                </div>
              </div>
            </Card>
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { ForecastPage, FormulaPage, yuanC, wanC, CAP_C, formulaExample });

/* ================================================================
   3. 费用报工单价（财务录入 · 可编辑）
   科伦《费用报工》表 KL01-KL10：车间报工单价 / 辅助报工单价 / 税率
   样表中单价列标注「财务录入」，此处提供录入入口，改完 6 工况立即重算。
   ================================================================ */
const BASIS_LABEL = { water: '单批次水 × 批次', elec: '单批次电 × 批次', steam: '单批次汽 × 批次', labor: '日总人工（整段）', hours: '生产时长（整段小时）' };

function RateInput({ value, onCommit, step }) {
  const [text, setText] = useState(value == null ? '' : String(value));
  useEffect(() => { setText(value == null ? '' : String(value)); }, [value]);
  const commit = () => {
    const n = text === '' ? 0 : Number(text);
    if (!isNaN(n) && n !== Number(value)) onCommit(n);
  };
  return (
    <input className="input num" style={{ width: 96, textAlign: 'right', height: 28 }}
      value={text} step={step || '0.01'}
      onChange={(e) => setText(e.target.value)}
      onBlur={commit}
      onKeyDown={(e) => { if (e.key === 'Enter') e.target.blur(); }} />
  );
}

function RatesPage() {
  const app = useApp();
  const { factors, updateFactor, calc, role } = app;
  const canEdit = role === 'finance';
  const blank = factors.filter((f) => !f.wsPrice && !f.auxPrice).length;

  return (
    <div className="scroll" data-screen-label="费用报工单价">
      <div className="sec-title">
        <h2>费用报工单价</h2>
        <span className="sub">科伦《费用报工》KL01–KL10 · 单价由财务录入 · 修改后 6 个工况立即重算</span>
        <div className="right">
          {canEdit ? <Tag kind="primary" dot>可编辑</Tag> : <Tag><Ico name="lock" size={11} />只读</Tag>}
        </div>
      </div>

      {blank > 0 && (
        <div className="notice warn mb12">
          <span className="n-ico"><Ico name="alert" size={15} /></span>
          <div>有 <b>{blank} 项</b>费用的单价还是 0（KL07 检验费、KL08 非正常生产费用、KL09 其他费用、KL10 排污费，样表中单价为空）。单价为 0 时该项不计入成本，填上真实单价后即参与核算。</div>
        </div>
      )}

      <Card>
        <div className="tbl-wrap">
          <table className="tbl">
            <thead>
              <tr>
                <th style={{ width: 84 }}>费用编码</th>
                <th>费用名称</th>
                <th style={{ width: 76 }}>类别</th>
                <th style={{ width: 150 }}>报工量取数</th>
                <th className="r" style={{ width: 130 }}>车间报工单价</th>
                <th className="r" style={{ width: 130 }}>辅助报工单价</th>
                <th className="r" style={{ width: 110 }}>发票税率</th>
                <th style={{ width: 84 }}>计入</th>
              </tr>
            </thead>
            <tbody>
              {factors.map((f) => (
                <tr key={f.code}>
                  <td className="num" style={{ fontWeight: 500 }}>{f.code}</td>
                  <td>
                    <div className="primary-cell">{f.name}</div>
                    <div className="sub-cell">单位：{f.unit}</div>
                  </td>
                  <td><span className="tag" style={{ height: 19, fontSize: 10.5 }}>{f.cat}</span></td>
                  <td className="tiny muted">{BASIS_LABEL[f.basis]}</td>
                  <td className="r">
                    {canEdit
                      ? <RateInput value={f.wsPrice} onCommit={(n) => updateFactor(f.code, { wsPrice: n })} />
                      : <span className="num">{yuanC(f.wsPrice)}</span>}
                    <span className="tiny muted"> 元/{f.unit}</span>
                  </td>
                  <td className="r">
                    {canEdit
                      ? <RateInput value={f.auxPrice} onCommit={(n) => updateFactor(f.code, { auxPrice: n })} />
                      : <span className="num">{yuanC(f.auxPrice)}</span>}
                    <span className="tiny muted"> 元/{f.unit}</span>
                  </td>
                  <td className="r">
                    {canEdit
                      ? <RateInput value={Math.round(f.taxRate * 1000) / 10} step="1" onCommit={(n) => updateFactor(f.code, { taxRate: n / 100 })} />
                      : <span className="num">{Math.round(f.taxRate * 100)}%</span>}
                    {canEdit && <span className="tiny muted"> %</span>}
                  </td>
                  <td><span className="tag" style={{ height: 19, fontSize: 10.5 }}>{f.kind === 'depr' ? '折旧' : '付现'}</span></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </Card>

      <Card className="mt12">
        <CardHead title="按当前单价试算（M1）" sub="改单价后此处与成本核算结果页同步变化" />
        <div className="card-body">
          <div className="grid g4">
            {[['车间付现（含税）', calc['M1'].factors.wsCash.tax], ['车间折旧（含税）', calc['M1'].factors.wsDepr.tax], ['辅助付现（含税）', calc['M1'].factors.auxCash.tax], ['辅助折旧（含税）', calc['M1'].factors.auxDepr.tax]].map(([k, v]) => (
              <div key={k}>
                <div className="tiny muted">{k}</div>
                <div className="num" style={{ fontSize: 16, fontWeight: 600, marginTop: 4 }}>{yuanC(v)}<span className="tiny muted"> 元</span></div>
              </div>
            ))}
          </div>
          <div className="notice flat mt12">
            <span className="n-ico"><Ico name="info" size={14} /></span>
            <div>KL01–KL06 的单价是示例值（样表中该列为空、标注「财务录入」），请替换为真实单价。折旧类（KL05 折旧费、KL08 非正常生产费用）计入折旧，其余计入付现。此处的修改仅在本次打开中生效，刷新页面恢复初始值。</div>
          </div>
        </div>
      </Card>
    </div>
  );
}

Object.assign(window, { ForecastPage, FormulaPage, RatesPage, yuanC, wanC, CAP_C, formulaExample });
