/* ============================================================
   blocks.jsx — 跨页面复用的业务块
   流程条 / 审计时间线 / 数据来源标记 / 差异表
   ============================================================ */
const { Ico, Btn, Tag, Card, CardHead, Empty, Bar, Ring, StackBar } = window;



/* 流程条：发起 → 生产部 → 供应部 → 财务审批 */
function FlowStepper({ decl, compact }) {
  const steps = window.STEPS;
  const rejectedAt = decl.status === 'rejected' ? decl.step : -1;
  return (
    <div className="flow">
      {steps.map((s, i) => {
        const done = decl.status === 'approved' ? true : i < decl.step;
        const cur = decl.status !== 'approved' && i === decl.step;
        const bad = decl.status === 'rejected' && i === rejectedAt;
        let cls = 'flow-chip';
        if (bad) cls += ' rejected'; else if (done) cls += ' done'; else if (cur) cls += ' current';
        return (
          <div className="flow-node" key={s.key}>
            <div className={cls} title={s.dept + ' · ' + s.owner}>
              <span className="idx">{bad ? '!' : done ? '✓' : i + 1}</span>
              <span className="nm">{s.name}</span>
            </div>
            {i < steps.length - 1 && <div className={'flow-line' + (done ? ' done' : '')} />}
          </div>
        );
      })}
    </div>
  );
}

/* 迷你流程点 */
function MiniSteps({ decl }) {
  const steps = window.STEPS;
  return (
    <div className="mini-steps" title={steps.map((s, i) => s.name + (i < decl.step ? ' ✓' : '')).join(' → ')}>
      {steps.map((s, i) => {
        const done = i < decl.step, cur = i === decl.step && decl.status !== 'approved';
        const bad = decl.status === 'rejected' && i === decl.step;
        return (
          <span className="st" key={s.key}>
            <span className={'dot2' + (bad ? ' bad' : done ? ' ok' : cur ? ' cur' : '')} />
            {i < steps.length - 1 && <span className={'ln' + (done ? ' ok' : '')} />}
          </span>
        );
      })}
    </div>
  );
}

/* 单个时间线节点 */
function TLItem({ e, last }) {
  const cls = 'tl-item ' + (e.rejectTo ? 'bad' : e.ok ? 'ok' : 'bad');
  return (
    <div className={cls}>
      <span className="node" />
      <div className="tl-head">
        <span className="tl-title">{e.act}</span>
        <span className="tag plain" style={{ fontSize: 11.5 }}>{e.who} · {e.dept}</span>
        <span className="tl-time">{e.t}</span>
      </div>
      {e.note && <div className={'tl-quote'}>{e.note}</div>}
      {e.rejectTo && !e.note && <div className="tl-quote">已驳回至「{e.rejectTo}」节点</div>}
      {e.rejectTo && e.note && (
        <div className="tiny muted" style={{ marginTop: 6 }}>回退节点：<b style={{ color: 'var(--danger)' }}>{e.rejectTo}</b></div>
      )}
      {e.changes && e.changes.length > 0 && (
        <div className="tl-diff">
          {e.changes.map((c, i) => (
            <div className="row" key={i}>
              <span className="k">{[c.product, c.k].filter(Boolean).join(' · ')}</span>
              <span className="v">
                {c.from && <del>{c.from}</del>}
                {c.from && <Ico name="arrowRight" size={12} style={{ color: 'var(--ink-4)' }} />}
                {c.to && <ins>{c.to}</ins>}
              </span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function Timeline({ events, dense }) {
  return (
    <div className="tl" style={dense ? { fontSize: 12 } : undefined}>
      {events.slice().reverse().map((e, i, arr) => <TLItem key={i} e={e} last={i === arr.length - 1} />)}
    </div>
  );
}

/* 数据来源标记 */
function SrcDot({ src }) {
  const meta = window.SRC_META[src] || window.SRC_META.calc;
  return <i className={'src-dot ' + meta.dot} title={meta.label} />;
}

/* 字段单元格 + 来源 */
function FieldCell({ value, src, mono, sub, muted }) {
  return (
    <div>
      <div className={mono ? 'num' : ''} style={{ fontWeight: 500, color: muted ? 'var(--ink-3)' : 'var(--ink)' }}>{value}</div>
      {sub && <div className="sub-cell">{sub}</div>}
      {src && <div className="provenance" style={{ marginTop: 2 }}><SrcDot src={src} />{window.SRC_META[src].label}</div>}
    </div>
  );
}

/* 差异处理表 */
function DiffTable({ diffs, onResolve }) {
  const statusTag = (s) => s === 'open' ? <Tag kind="warn" dot>待确认</Tag> : s === 'stale' ? <Tag kind="danger" dot>本地值过期</Tag> : <Tag kind="ok">已处理</Tag>;
  return (
    <div className="tbl-wrap">
      <table className="tbl">
        <thead>
          <tr>
            <th style={{ width: 116 }}>物料 / 对象</th>
            <th>字段</th>
            <th className="r" style={{ width: 106 }}>系统本地值</th>
            <th className="r" style={{ width: 106 }}>外部来源值</th>
            <th style={{ width: 168 }}>来源凭据</th>
            <th style={{ width: 100 }}>状态</th>
            <th style={{ width: 130 }}>影响产品</th>
            <th style={{ width: 96 }} className="r">操作</th>
          </tr>
        </thead>
        <tbody>
          {diffs.map((d) => (
            <tr key={d.id}>
              <td>
                <div className="primary-cell num" style={{ fontSize: 12.5 }}>{d.mid}</div>
              </td>
              <td>{d.field}</td>
              <td className="r num">{d.local.toLocaleString()} <span className="muted tiny">{d.unit}</span></td>
              <td className="r num" style={Number(d.remote) !== Number(d.local) ? { color: 'var(--danger)', fontWeight: 600 } : {}}>
                {d.remote.toLocaleString()} <span className="muted tiny">{d.unit}</span>
              </td>
              <td><span className="tiny muted">{d.from}</span></td>
              <td>{d.status === 'stale' ? <span className="row" style={{ gap: 5 }}><Tag kind="danger" dot>超 {d.staleDays} 天</Tag></span> : statusTag(d.status)}</td>
              <td>
                <div className="row wrap" style={{ gap: 4 }}>
                  {d.impact.map((p) => <span className="tag" key={p} style={{ height: 19, fontSize: 10.5 }}>{p}</span>)}
                </div>
              </td>
              <td className="r">
                {d.status === 'open' ? (
                  <div className="row" style={{ justifyContent: 'flex-end', gap: 4 }}>
                    <button className="btn sm" onClick={() => onResolve(d.id, 'accept')}>采纳</button>
                    <button className="btn sm ghost" onClick={() => onResolve(d.id, 'keep')}>保留</button>
                  </div>
                ) : <span className="tiny muted">—</span>}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

/* 数据完整度面板 —— “卡在哪一环、缺哪个字段” */
function CompletenessPanel({ product, completeness, decls, onJump }) {
  const items = completeness[product.id] || [];
  const done = items.filter((x) => x.ok).length;
  const pct = items.length ? (done / items.length) * 100 : 0;
  const missing = items.filter((x) => !x.ok);
  const blockedBy = [...new Set(missing.map((m) => m.src))];
  return (
    <div>
      <div className="row" style={{ gap: 12, alignItems: 'center' }}>
        <Ring value={pct} size={58} label={done + '/' + items.length} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 12.5, fontWeight: 500 }}>
            {pct === 100 ? '数据齐备，可核算' : '数据未齐备，暂不能出具正式预测'}
          </div>
          <div className="tiny muted mt8" style={{ lineHeight: 1.6 }}>
            {pct === 100
              ? '全部 6 项参数已采集并确认，公式可完整求值。'
              : <>缺少 {missing.length} 项：{missing.map((m) => m.k).join('、')}，需 <b style={{ color: 'var(--warn)' }}>{blockedBy.join(' / ')}</b> 补充。</>}
          </div>
        </div>
      </div>
      <div className="divider" />
      <div className="col" style={{ gap: 7 }}>
        {items.map((it, i) => (
          <div className="row" key={i} style={{ gap: 9 }}>
            <span style={{
              width: 15, height: 15, borderRadius: 4, display: 'grid', placeItems: 'center', flex: '0 0 auto',
              background: it.ok ? 'var(--ok)' : 'var(--surface-3)', color: '#fff',
            }}>{it.ok ? <Ico name="check" size={10} /> : null}</span>
            <span style={{ fontSize: 12.5, color: it.ok ? 'var(--ink)' : 'var(--ink-3)' }}>{it.k}</span>
            <span className="spacer" />
            <span className="tag" style={{ height: 19, fontSize: 10.5, background: it.ok ? 'var(--surface-3)' : 'var(--warn-soft)', color: it.ok ? 'var(--ink-3)' : 'var(--warn)' }}>{it.src}</span>
          </div>
        ))}
      </div>
      {missing.length > 0 && (
        <div className="notice warn mt12">
          <span className="n-ico"><Ico name="alert" size={15} /></span>
          <div>
            本页计算出的 <b>{product.id}</b> 结果为基础试算值，标记为「暂定」，不计入已发布预测总额。
            {onJump && <> <span className="linkish" onClick={onJump}>前往催办 →</span></>}
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { FlowStepper, MiniSteps, Timeline, TLItem, SrcDot, FieldCell, DiffTable, CompletenessPanel });
