// TodoDetailParts — TODO 詳細(Screens.jsx TodoDetail)の 1 カラムの部品(K18-27・K18-28)。
// ==================================================================
// 池田さんの画面編集版(reference/ikeda-2026-09-16/screens/marurou/Screens.jsx の TodoDetail)と
// UI 設計仕様 v0.20 追記 1・2 の並び(TODO 情報 → 工程 → 書類 → 活動履歴)に寄せる部品だけを置く。
// 値の計算(scMicro・scTargets など)と保存(finish・persistContact・issueDoc・sendShare)は Screens.jsx の
// まま ─ ここは受け取った値を並べるだけで、店(MStore)にも書き込み層にも触らない。
// 池田さん版の Page/Card/Table/Field(デザインシステムの部品)は main に無い(採否は K18-40)ので、
// 見た目は既存の Af* とトークンで組む。

const TD_CAPTION = { fontSize:"var(--text-caption)", fontWeight:600, letterSpacing:"0.04em", color:"var(--muted-foreground)" };

/** TODO 情報の表(4 列・狭い幅では自動で 2〜3 列)。items: [{ label, value, key? }]。null は飛ばす。 */
function TdInfoGrid({ items }) {
  const list = (items || []).filter(Boolean);
  return (
    <div data-todo-info="" style={{ display:"grid", gap:"12px 16px",
      /* 広い幅は 4 列(25% - 列間 16px×3/4)。狭くなると 150px を割らない範囲で列が減る。 */
      gridTemplateColumns:"repeat(auto-fill, minmax(max(150px, calc(25% - 12px)), 1fr))" }}>
      {list.map(it => (
        <div key={it.key || it.label} data-todo-field={it.label} style={{ minWidth:0 }}>
          <div style={{ ...TD_CAPTION, marginBottom:3 }}>{it.label}</div>
          <div style={{ fontSize:"var(--text-body-md)", color:"var(--foreground)", minWidth:0, overflowWrap:"anywhere" }}>{it.value}</div>
        </div>
      ))}
    </div>
  );
}

/* 内訳の状態の見せ方。done=済・now=今ここ・todo=まだ。 */
const TD_STEP_STATE = {
  done: { label:"済", color:"var(--success)", bg:"var(--success-muted)", border:"var(--success-border)" },
  now:  { label:"今ここ", color:"var(--brand)", bg:"var(--brand-muted)", border:"var(--brand-border)" },
  todo: { label:"まだ", color:"var(--foreground-subtle)", bg:"transparent", border:"var(--border)" },
};
const TD_TH = { ...TD_CAPTION, textAlign:"left", padding:"7px 10px", borderBottom:"1px solid var(--border)", background:"var(--accent)", whiteSpace:"nowrap" };
const TD_TD = { padding:"8px 10px", borderBottom:"1px solid var(--border)", verticalAlign:"middle", fontSize:"var(--text-body-md)" };

/** このTODOの内訳(工程)の表。列は 段・状態・工程・共有・操作。
 *  操作のボタンは「今ここ」の段にだけ出す(先の段を押すと順番が崩れる ─ 以前の横並びと同じ決め)。
 *  各行の data-micro-step / data-state は E2E が状態を読む印(tests/e2e/todo-detail.spec.js)。 */
function TdStepTable({ steps, onAct }) {
  const rows = Array.isArray(steps) ? steps : [];
  return (
    <div style={{ border:"1px solid var(--border)", borderRadius:"var(--radius-md)", overflowX:"auto" }}>
      <table data-micro-steps="" style={{ width:"100%", borderCollapse:"collapse", fontFamily:"var(--font-sans)" }}>
        <thead>
          <tr>
            <th style={{ ...TD_TH, width:28 }}>段</th>
            <th style={{ ...TD_TH, width:72 }}>状態</th>
            <th style={TD_TH}>工程</th>
            <th style={{ ...TD_TH, width:64 }}>共有</th>
            <th style={{ ...TD_TH, width:1 }}>操作</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((x, i) => {
            const st = TD_STEP_STATE[x.s] || TD_STEP_STATE.todo;
            const now = x.s === "now", done = x.s === "done";
            const last = i === rows.length - 1;
            const td = last ? { ...TD_TD, borderBottom:"none" } : TD_TD;
            return (
              <tr key={i} data-micro-step={i} data-state={x.s} style={{ background: now ? "var(--brand-muted)" : "transparent" }}>
                <td className="mono" style={{ ...td, color:"var(--foreground-subtle)" }}>{i + 1}</td>
                <td style={td}>
                  <span style={{ display:"inline-flex", alignItems:"center", gap:4, height:18, padding:"0 7px", borderRadius:"var(--radius-sm)",
                    fontSize:"var(--text-caption)", fontWeight:700, whiteSpace:"nowrap", color:st.color, background:st.bg, border:"1px solid "+st.border }}>
                    {done ? "✓ " : ""}{st.label}
                  </span>
                </td>
                <td style={{ ...td, fontWeight: now ? 700 : 500, color: done ? "var(--muted-foreground)" : now ? "var(--foreground)" : "var(--foreground-subtle)" }}>{x.t}</td>
                <td className="mono" style={{ ...td, fontSize:"var(--text-caption)", fontWeight:700, whiteSpace:"nowrap",
                  color: done ? "var(--success)" : "var(--muted-foreground)" }}>{x.count || "—"}</td>
                <td style={{ ...td, whiteSpace:"nowrap", textAlign:"right" }}>
                  {now && onAct && x.act
                    ? <button onClick={() => onAct(i)} style={{ all:"unset", cursor:"pointer", fontFamily:"var(--font-sans)",
                        fontSize:"var(--text-caption)", fontWeight:700, color:"#fff", background:"var(--brand)",
                        padding:"4px 10px", borderRadius:"var(--radius-sm)", whiteSpace:"nowrap" }}>{x.act} ›</button>
                    : now ? <span style={{ fontSize:"var(--text-caption)", fontWeight:700, color:"var(--brand)" }}>ここ</span>
                    : <span style={{ color:"var(--foreground-subtle)" }}>—</span>}
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

/* ── K18-28: 書類の表と、受領・書類作成のモーダル ─────────────────────────
   共有のモーダルは Screens.jsx の ScShareModal(宛先は actorId のある関係者だけ・0044 の決め)をそのまま使う。 */

/* 書類の状態の見せ方(受領/下書き/確定)。Screens.jsx の SC_STAGE と同じ語。 */
const TD_FILE_STAGE = { received:["受領","var(--status-survey)","var(--status-survey-muted)","var(--status-survey-border)"],
  draft:["下書き","var(--warning)","var(--warning-muted)","var(--warning-border)"],
  issued:["確定","var(--success)","var(--success-muted)","var(--success-border)"] };
const TD_LINK = { all:"unset", cursor:"pointer", fontFamily:"var(--font-sans)", fontSize:"var(--text-caption)", fontWeight:600, color:"var(--brand)" };

/** このTODOの書類の表。列は 状態・書類・日付・共有・操作(池田さん版 ScFileStrip)。
 *  操作は 見る(プレビュー/編集)と、下書きだけ「確定にする」。空なら何が無いかを 1 行で言う。 */
function TdFileTable({ files, kindOf, onView, onFinalize }) {
  const rows = Array.isArray(files) ? files : [];
  if (!rows.length) return (
    <div data-todo-files="" style={{ fontSize:"var(--text-body-sm)", color:"var(--foreground-subtle)" }}>
      {(kindOf || "書類") + "はまだありません（受領・作成すると残ります）"}
    </div>
  );
  return (
    <div style={{ border:"1px solid var(--border)", borderRadius:"var(--radius-md)", overflowX:"auto" }}>
      <table data-todo-files="" style={{ width:"100%", borderCollapse:"collapse", fontFamily:"var(--font-sans)" }}>
        <thead>
          <tr>
            <th style={{ ...TD_TH, width:64 }}>状態</th>
            <th style={TD_TH}>書類</th>
            <th style={{ ...TD_TH, width:56 }}>日付</th>
            <th style={TD_TH}>共有</th>
            <th style={{ ...TD_TH, width:1 }}>操作</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((f, i) => {
            const st = TD_FILE_STAGE[f.stage] || ["—","var(--muted-foreground)","var(--muted)","var(--border)"];
            const td = i === rows.length - 1 ? { ...TD_TD, borderBottom:"none" } : TD_TD;
            const shared = Array.isArray(f.sharedTo) ? f.sharedTo : [];
            return (
              <tr key={f.id} data-todo-file={f.name}>
                <td style={td}>
                  <span style={{ display:"inline-flex", alignItems:"center", height:18, padding:"0 7px", borderRadius:"var(--radius-sm)",
                    fontSize:"var(--text-caption)", fontWeight:700, whiteSpace:"nowrap", color:st[1], background:st[2], border:"1px solid "+st[3] }}>{st[0]}</span>
                </td>
                <td style={{ ...td, minWidth:0 }}>
                  <button onClick={() => onView && onView(f)} style={{ ...TD_LINK, fontSize:"var(--text-body-md)", color:"var(--foreground)", overflowWrap:"anywhere" }}>{f.name}</button>
                </td>
                <td className="mono" style={{ ...td, fontSize:"var(--text-caption)", color:"var(--foreground-subtle)", whiteSpace:"nowrap" }}>{f.date || "—"}</td>
                <td style={{ ...td, fontSize:"var(--text-caption)", color: shared.length ? "var(--success)" : "var(--foreground-subtle)" }}>
                  {shared.length ? shared.join("・") : "—"}
                </td>
                <td style={{ ...td, whiteSpace:"nowrap", textAlign:"right" }}>
                  <span style={{ display:"inline-flex", gap:10 }}>
                    <button onClick={() => onView && onView(f)} style={TD_LINK}>{f.docBody ? "編集" : "プレビュー"}</button>
                    {f.stage === "draft" && onFinalize && <button onClick={() => onFinalize(f)} style={{ ...TD_LINK, fontWeight:700, color:"var(--success)" }}>確定にする</button>}
                  </span>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

/** 受領のモーダル(K18-28)。受領はアップロードで行う ─ メール・LINE の添付の取り込み(受信箱)は本番ではまだ空
 *  (Screens.jsx scInboxFor)。受信箱に何か届く日が来たら、そのときだけ選択欄を出す(inboxView)。
 *  onPick(files) は保存の結果 { ok, message } を返す Promise。失敗はモーダルの中で言い、閉じない。 */
function TdReceiveModal({ kindOf, where, step, receivedCount, marksStep, inboxView, onPick, onClose }) {
  const Modal = window.ScModal, Btn = window.AfButton, Fail = window.AfSaveFail, Alert = window.AfAlert;
  const inputRef = React.useRef(null);
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState("");
  const pick = async list => {
    if (!list.length || busy) return;
    setBusy(true); setError("");
    try {
      const r = await Promise.resolve(onPick(list));
      if (r && r.ok === false) { setError(r.message || "受領できませんでした。"); return; }
      onClose && onClose();
    } catch (e) {
      setError((e && e.message) || "受領できませんでした。");
    } finally { setBusy(false); }
  };
  const label = kindOf || "書類";
  return (
    /* 閉じるは右上の ✕ だけ(仕様 03 v0.20 追記 2)。主操作は本文の「ファイルを選ぶ」1 つ。 */
    <Modal title={label + "を受け取る"} sub={step} onClose={onClose}>
      <div data-todo-receive="" style={{ fontSize:"var(--text-body-md)", color:"var(--muted-foreground)", lineHeight:1.7 }}>
        {label + "のファイルを選ぶと "}<b style={{ color:"var(--foreground)" }}>{where}</b>{" に格納されます。"}
        {marksStep ? "内訳の「受領」の段が済みになります。" : ""}
      </div>
      <input ref={inputRef} type="file" multiple style={{ display:"none" }}
        onChange={ev => { const l = [...ev.target.files]; ev.target.value = ""; pick(l); }} />
      <div style={{ display:"flex", alignItems:"center", gap:10, flexWrap:"wrap" }}>
        <Btn variant="primary" disabled={busy} onClick={() => inputRef.current && inputRef.current.click()}>{busy ? "アップロード中…" : "ファイルを選ぶ"}</Btn>
        {receivedCount > 0 && <span style={{ fontSize:"var(--text-caption)", color:"var(--success)" }}>{"受領済み " + receivedCount + "件（書類の表で確認）"}</span>}
      </div>
      {error && (Fail
        ? <Fail reason={error} title="受領できませんでした" onRetry={() => setError("")} onDismiss={() => setError("")} />
        : Alert ? <Alert variant="error" title="受領できませんでした">{error}</Alert> : <div role="alert">{error}</div>)}
      {inboxView || (
        <div style={{ fontSize:"var(--text-caption)", color:"var(--foreground-subtle)", lineHeight:1.7 }}>
          メール・LINE で届いた添付の取り込みはまだありません（受信箱は空です）。届いたファイルは端末に保存してから選んでください。
        </div>
      )}
    </Modal>
  );
}

/** 書類作成のモーダル(K18-28)。決-8: 帳票の本文は書かない・PDF は作らない ─ 残すのは「いつ・誰に・何を発行したか」の
 *  記録だけ(doc_issues・0084)。池田さん版の本文入力欄は持ち込まない。主操作は「発行を記録して工程を進める」。 */
function TdDocModal({ kindOf, who, step, onIssue, onPickRecipient, onClose }) {
  const Modal = window.ScModal, Btn = window.AfButton;
  const label = kindOf || "書類";
  return (
    <Modal title={label + "を作る"} sub={step} onClose={onClose}
      footer={<React.Fragment>
        <Btn onClick={() => onIssue(false)}>下書きとして記録</Btn>
        <Btn variant="primary" onClick={() => onIssue(true)}>発行を記録して工程を進める</Btn>
      </React.Fragment>}>
      <div data-todo-doc="" style={{ fontSize:"var(--text-body-md)", color:"var(--muted-foreground)", lineHeight:1.7 }}>
        本文は入力しません。宛先（<b style={{ color:"var(--foreground)" }}>{who || "未設定"}</b>）と発行日だけを記録します。PDFは作りません（送付はシステム外です）。
      </div>
      {onPickRecipient && <button onClick={onPickRecipient} style={{ ...TD_LINK, alignSelf:"flex-start" }}>宛先を選んで記録 ›</button>}
    </Modal>
  );
}

Object.assign(window, { TdInfoGrid, TdStepTable, TdFileTable, TdReceiveModal, TdDocModal });
