// マルロウ 漏水案件OS — 状況把握ボード（背骨§8 / S2-D1 v_board 接続）。
// 3ゾーン（滞り / やること / 待ち）＋ 集約軸切替（担当者 / 役割 / 案件）。受け身把握が主・入力は従。
// dark プロトを アクアフロー Design System（light・密・水色）へ移植。

// ── v_board 相当データ（メイプル405・CASE-2460 ＋ 別案件）。zone は導出（ここでは埋め込み） ──
// ball 8値: 自社 / 業者 / 依頼者 / 居住者 / 原因者 / 加入者 / 保険会社 / 鑑定会社
const BOARD_ROWS = [
  { trk: 'TRK-1', caseId: 'AQ-2026-2460', prop: 'メイプルコート405', cat: '調査',
    step: '日程調整（205 再訪）', ball: '居住者', assignee: '担当者A', role: '日程調整',
    due: '2026/06/16', stalled: false, target: '205 居住者・佐藤', next: '在宅日確定 → 被害確認（205）' },
  { trk: 'TRK-2', caseId: 'AQ-2026-2460', prop: 'メイプルコート405', cat: '原因箇所工事',
    step: '社内承認A（見積金額の決裁）', ball: '自社', assignee: '担当者A', role: '見積',
    due: '2026/06/15', stalled: false, target: null, next: '承認 → 社外承認B（原因者・山田）' },
  { trk: 'TRK-3', caseId: 'AQ-2026-2460', prop: 'メイプルコート405', cat: '被害箇所工事',
    step: '認定（着工ゲート P2）', ball: '保険会社', assignee: '担当者A', role: '保険',
    due: '2026/06/20', stalled: false, target: '日新火災', next: '認定 → 工事日程調整（305）' },
  { trk: 'TRK-4', caseId: 'AQ-2026-2460', prop: 'メイプルコート405', cat: '被害箇所工事',
    step: '社外承認B（復旧範囲の承認）', ball: '依頼者', assignee: '担当者A', role: '見積',
    due: '2026/06/13', stalled: true, target: 'シーサイド管理（205）', next: '承認 → 保険申請（205）' },
  { trk: 'TRK-6', caseId: 'AQ-2026-2460', prop: 'メイプルコート405', cat: '保険',
    step: '保険金請求（加入者の手続き）', ball: '加入者', assignee: '担当者A', role: '保険',
    due: '2026/06/10', stalled: true, target: '加入者・山田', next: '請求 → 入金待ち' },
  // 別案件（集約軸＝担当者で同一担当に複数案件が集まることを示す）
  { trk: 'TRK-1', caseId: 'AQ-2026-2477', prop: 'リバーサイド和泉 201', cat: '調査',
    step: '現地対応（原因特定）', ball: '業者', assignee: '担当者A', role: '日程調整',
    due: '2026/06/17', stalled: false, target: '協力業者・及川設備', next: '原因特定 → 方針確定' },
  { trk: 'TRK-2', caseId: 'AQ-2026-2477', prop: 'リバーサイド和泉 201', cat: '原因箇所工事',
    step: '見積作成', ball: '業者', assignee: '担当者A', role: '見積',
    due: '2026/06/14', stalled: true, target: '協力業者・及川設備', next: '見積 → 社内承認A' },
];

// 工事区分 → 低彩度カテゴリ色（Design System の work-type categorical set を流用）
const CAT_TONE = { '調査': 'w-drainage', '原因箇所工事': 'w-supply', '被害箇所工事': 'w-waterproof', '保険': 'w-fixture', '精算': 'neutral' };
const CAT_ORDER = ['調査', '原因箇所工事', '被害箇所工事', '保険', '精算'];

// 8値ボール: 1文字バッジ。自社＝brand（自分の番が目立つ）・他＝静かなsubtle。
const BALL8 = {
  '自社':   { ja: '自', self: true },
  '業者':   { ja: '工' },
  '依頼者': { ja: '依' },
  '居住者': { ja: '住' },
  '原因者': { ja: '因' },
  '加入者': { ja: '加' },
  '保険会社': { ja: '保' },
  '鑑定会社': { ja: '鑑' },
};

function Ball8({ who }) {
  const b = BALL8[who] || { ja: '—' };
  return <span style={{
    display: 'inline-flex', alignItems: 'center', gap: 4, height: 18, padding: '0 6px 0 3px',
    borderRadius: 'var(--radius-sm)', fontSize: 'var(--text-caption)', fontWeight: 600, whiteSpace: 'nowrap',
    background: b.self ? 'var(--brand-muted)' : 'var(--muted)', color: b.self ? 'var(--brand)' : 'var(--muted-foreground)',
    border: '1px solid ' + (b.self ? 'var(--brand-border)' : 'var(--border-strong)'),
  }}>
    <span style={{ width: 13, height: 13, borderRadius: 999, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontSize: 8, fontWeight: 700, flexShrink: 0,
      background: b.self ? 'var(--brand)' : 'var(--foreground-subtle)', color: '#fff' }}>{b.ja}</span>
    {who}
  </span>;
}

const BOARD_TODAY = new Date('2026-06-14T00:00:00');  // プロト基準日（サンプル状態を固定）
function daysLeft(due) { return Math.round((new Date(due.replace(/\//g, '-') + 'T00:00:00') - BOARD_TODAY) / 86400000); }

function zoneOf(r) { return r.stalled ? 'C' : (r.ball === '自社' ? 'A' : 'B'); }

function BoardRow({ r, onOpen, known }) {
  const [hover, setHover] = React.useState(false);
  const dl = daysLeft(r.due);
  const overdue = r.stalled || dl < 0;
  const approaching = !overdue && dl <= 1;
  const dueColor = overdue ? 'var(--destructive)' : approaching ? 'var(--warning)' : 'var(--muted-foreground)';
  const dueLabel = overdue ? Math.abs(dl) + '日超過' : dl === 0 ? '本日' : 'あと' + dl + '日';
  return (
    <div onClick={() => known && onOpen && onOpen(r.caseId)}
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{ display: 'flex', gap: 12, padding: '10px 14px', borderBottom: '1px solid var(--border)', alignItems: 'flex-start',
        cursor: known ? 'pointer' : 'default', background: hover && known ? 'var(--accent)' : 'transparent', transition: 'background var(--duration-fast) var(--easing)' }}>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
          <span style={{ fontSize: 'var(--text-body-lg)', fontWeight: 600, color: 'var(--foreground)' }}>{r.step}</span>
          <AfChip tone={CAT_TONE[r.cat] || 'neutral'}>{r.cat}</AfChip>
        </div>
        <div style={{ display: 'flex', gap: 8, marginTop: 4, flexWrap: 'wrap', alignItems: 'center' }}>
          <span className="code" style={{ fontSize: 'var(--text-caption)', color: 'var(--brand)' }}>{r.trk}</span>
          <span style={{ fontSize: 'var(--text-body-sm)', color: 'var(--muted-foreground)' }}>{r.prop}</span>
        </div>
        <div style={{ fontSize: 'var(--text-body-sm)', color: 'var(--foreground-subtle)', marginTop: 4 }}>次：{r.next}</div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 6, flexShrink: 0 }}>
        <span className="mono" style={{ fontSize: 'var(--text-body-md)', fontWeight: 700, color: dueColor }}>{dueLabel}</span>
        <Ball8 who={r.ball} />
        {r.target && (r.stalled || r.ball !== '自社') &&
          <span style={{ fontSize: 'var(--text-caption)', color: r.stalled ? 'var(--destructive)' : 'var(--muted-foreground)' }}>
            {r.stalled ? '督促 → ' : '待ち → '}{r.target}</span>}
      </div>
    </div>
  );
}

function BoardZone({ title, hint, accent, rows, onOpen }) {
  return (
    <AfCard pad={0} style={{ overflow: 'hidden' }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, padding: '11px 14px', borderBottom: '1px solid var(--border)' }}>
        <span style={{ width: 8, height: 8, borderRadius: 999, background: accent, alignSelf: 'center', flexShrink: 0 }} />
        <span style={{ fontSize: 'var(--text-display-sm)', fontWeight: 600, letterSpacing: 'var(--tracking-tight)' }}>{title}</span>
        <span className="mono" style={{ fontSize: 'var(--text-body-lg)', fontWeight: 700, color: accent }}>{rows.length}</span>
        <div style={{ flex: 1 }} />
        <span style={{ fontSize: 'var(--text-body-sm)', color: 'var(--foreground-subtle)' }}>{hint}</span>
      </div>
      {rows.length === 0
        ? <div style={{ padding: '16px 14px', fontSize: 'var(--text-body-sm)', color: 'var(--foreground-subtle)' }}>なし</div>
        : rows.map((r, i) => <BoardRow key={r.caseId + r.trk + i} r={r} onOpen={onOpen} known={CASES.some(c => c.id === r.caseId)} />)}
    </AfCard>
  );
}

function StatusBoard({ onOpen }) {
  const [axis, setAxis] = React.useState('person');
  const axes = {
    person: { label: '担当者', opts: ['担当者A'], key: 'assignee', note: 'Phase 1：本担当が自分の全トラックを案件横断で（個人縦割り）' },
    role:   { label: '役割',   opts: ['見積', '日程調整', '保険'], key: 'role', note: 'Phase 2：役割チームが全案件の同種工程だけを（役割分業）' },
    case:   { label: '案件',   opts: ['AQ-2026-2460', 'AQ-2026-2477'], key: 'caseId', note: '補助：1案件の全トラック状態を俯瞰（先回り入力もここから）' },
  };
  const cur = axes[axis];
  const [val, setVal] = React.useState(cur.opts[0]);

  const filtered = BOARD_ROWS.filter(r => r[cur.key] === val).sort((a, b) => CAT_ORDER.indexOf(a.cat) - CAT_ORDER.indexOf(b.cat));
  const A = filtered.filter(r => zoneOf(r) === 'A');
  const B = filtered.filter(r => zoneOf(r) === 'B');
  const C = filtered.filter(r => zoneOf(r) === 'C');

  const segWrap = { display: 'flex', gap: 2, background: 'var(--muted)', padding: 3, borderRadius: 'var(--radius-md)' };
  const seg = (on) => ({ all: 'unset', boxSizing: 'border-box', cursor: 'pointer', fontSize: 'var(--text-body-md)', fontWeight: 600,
    padding: '5px 11px', borderRadius: 'var(--radius-sm)', whiteSpace: 'nowrap',
    background: on ? 'var(--card)' : 'transparent', color: on ? 'var(--brand)' : 'var(--muted-foreground)', boxShadow: on ? 'var(--shadow-sm)' : 'none' });
  const valChip = (on) => ({ all: 'unset', boxSizing: 'border-box', cursor: 'pointer', fontSize: 'var(--text-body-md)',
    padding: '5px 10px', borderRadius: 'var(--radius-md)', whiteSpace: 'nowrap',
    border: '1px solid ' + (on ? 'var(--brand)' : 'var(--border)'), background: on ? 'var(--brand-muted)' : 'var(--card)', color: on ? 'var(--foreground)' : 'var(--muted-foreground)' });

  return (
    <div style={{ padding: '20px 24px 32px 20px', maxWidth: '980px' }}>
      <div style={{ fontSize: 'var(--text-body-sm)', color: 'var(--muted-foreground)', marginBottom: 14 }}>
        やること・待ち・滞りを受け身で把握。同じ盤面を軸だけ替えて見る（体制移行対応）。
      </div>

      {/* 集約軸切替 */}
      <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center', marginBottom: 8 }}>
        <div style={segWrap}>
          {Object.entries(axes).map(([k, a]) => (
            <button key={k} style={seg(axis === k)} onClick={() => { setAxis(k); setVal(a.opts[0]); }}>{a.label}で見る</button>
          ))}
        </div>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          {cur.opts.map(o => <button key={o} style={valChip(val === o)} onClick={() => setVal(o)}>{o}</button>)}
        </div>
      </div>
      <div style={{ fontSize: 'var(--text-body-sm)', color: 'var(--foreground-subtle)', marginBottom: 16 }}>{cur.note}</div>

      {/* ゼロ運用サマリ（滞り総数を主） */}
      <div style={{ display: 'flex', gap: 10, marginBottom: 16, flexWrap: 'wrap' }}>
        <SummaryPill label="滞り" n={C.length} accent="var(--destructive)" emphasize />
        <SummaryPill label="やること" n={A.length} accent="var(--brand)" />
        <SummaryPill label="待ち" n={B.length} accent="var(--foreground-subtle)" />
      </div>

      {/* 3ゾーン */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <BoardZone title="滞り" hint="相手の番・期限超過 ＝ 督促する" accent="var(--destructive)" rows={C} onOpen={onOpen} />
        <BoardZone title="やること" hint="自分の番 ＝ いま動く" accent="var(--brand)" rows={A} onOpen={onOpen} />
        <BoardZone title="待ち" hint="相手の番・期限内 ＝ 静かに見張る" accent="var(--foreground-subtle)" rows={B} onOpen={onOpen} />
      </div>

      <div style={{ fontSize: 'var(--text-caption)', color: 'var(--foreground-subtle)', marginTop: 16, lineHeight: 1.7 }}>
        供給：v_board（v_track_current_step ＋ v_track_stalled ＋ f_step_deadline）。完了トラックは盤面から自然に消える（ゼロ運用）。行クリックで案件詳細へ。
      </div>
    </div>
  );
}

function SummaryPill({ label, n, accent, emphasize }) {
  return (
    <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, padding: '8px 14px', background: 'var(--card)', border: '1px solid ' + (emphasize && n > 0 ? 'var(--destructive-border)' : 'var(--border)'), borderRadius: 'var(--radius-lg)' }}>
      <span style={{ width: 8, height: 8, borderRadius: 999, background: accent, alignSelf: 'center' }} />
      <span style={{ fontSize: 'var(--text-body-md)', fontWeight: 600, color: 'var(--muted-foreground)' }}>{label}</span>
      <span className="mono" style={{ fontSize: 'var(--text-display-md)', fontWeight: 700, color: n > 0 ? accent : 'var(--foreground-subtle)' }}>{n}</span>
    </div>
  );
}

Object.assign(window, { StatusBoard });
