// ClientRulesBand — 依頼者規定の帯(K18-18)。案件詳細・下請手配・受付の 3 か所が使う部品は、ここ 1 か所に置く。
// ==================================================================
// 何を出すか(仕様 04 v1.24:130-132・02 v0.32:763・池田さん画面版 CaseDetailV26.jsx:331):
//   ・取引条件(tradeTerms)        … 案件詳細と下請手配(業者手配)に常に出す
//   ・初動対応注意点(firstResponseNotes) … 受付で依頼先を選んだときに出す。案件詳細の帯にも並べる(02:763・画面版)
//   ・報告投稿先(clientSystemName) … 案件詳細の帯を出すときだけ、補足として 1 行(画面版。docs/21 検証 1 の指摘)
//   帯は「出す欄(fields)のどれかに値があるとき」だけ出す。報告投稿先だけでは出さない(画面版の条件)。
//
// 値の出どころ(案件側に写さない):
//   依頼者(cases.requester_org_id)の取引先の値を、開くたびに取引先から読む。
//   ・案件詳細・下請手配 … rpc_case_detail_context の clientRules(0106)。店(store.jsx)はメモリにだけ控える
//     (MStore.clientRules)。案件の state にも localStorage にも入れない。
//   ・受付 … rpc_list_partners の行(0106 で同名の 4 キー)。選んだ候補の行をそのまま渡す。
//   池田さん版は案件側に持たせている(store.jsx:47 clientTerms)が、それだと取引先を直したときに
//   案件側が古いまま残るので採らない(docs/21 K18-18)。
//
// 取引先詳細(Screens.jsx PartnerDetail)の「取引条件」カードは 精算方式・関連案件・区分 の要約で、
// ここの取引条件(依頼者との約束事の自由記述)とは別物。見出しは「依頼者規定」にし、カードの部品は使い回さない。

// 帯に並べる欄。語は仕様 04 の項目名のまま(管理画面 Admin.jsx の入力欄と同じ言葉)。
const CLIENT_RULES_FIELDS = [
  { key: "tradeTerms", label: "取引条件" },
  { key: "firstResponseNotes", label: "初動対応注意点" },
];
const CLIENT_RULES_SYSTEM = { key: "clientSystemName", label: "報告投稿先" };

const crText = v => (typeof v === "string" ? v.trim() : "");

/** 帯に出す行。fields に無い欄と、空の欄は出さない。帯を出さないときは []。
 *  rules は { name, tradeTerms, firstResponseNotes, clientSystemName, … }(0106 の clientRules / rpc_list_partners の行)。 */
function clientRulesBandRows(rules, fields, showSystem) {
  if (!rules || typeof rules !== "object") return [];
  const keys = Array.isArray(fields) && fields.length ? fields : CLIENT_RULES_FIELDS.map(f => f.key);
  const rows = CLIENT_RULES_FIELDS
    .filter(f => keys.indexOf(f.key) >= 0 && crText(rules[f.key]))
    .map(f => ({ key: f.key, label: f.label, text: crText(rules[f.key]) }));
  if (!rows.length) return [];
  const system = showSystem ? crText(rules[CLIENT_RULES_SYSTEM.key]) : "";
  if (system) rows.push({ key: CLIENT_RULES_SYSTEM.key, label: CLIENT_RULES_SYSTEM.label, text: system, sub: true });
  return rows;
}

/** 帯そのもの。where は置き場所(case / dispatch / intake)で、E2E が data-client-rules-band で探す。
 *  見た目は池田さん画面版の .terms-band(左に太い線・brand の淡い地)に合わせる。 */
function ClientRulesBand({ rules, fields, showSystem, where, style }) {
  const rows = clientRulesBandRows(rules, fields, showSystem);
  if (!rows.length) return null;
  const name = crText(rules.name);
  return (
    <div role="note" aria-label="依頼者規定" data-client-rules-band={where || ""} style={{
      display: "flex", flexDirection: "column", gap: 4, padding: "9px 13px",
      border: "1px solid var(--brand-border)", borderLeft: "4px solid var(--brand)",
      background: "var(--brand-muted)", borderRadius: "var(--radius-md)",
      fontSize: "var(--text-body-sm)", lineHeight: 1.6, color: "var(--foreground)", ...(style || {}) }}>
      <div style={{ fontWeight: 700, color: "var(--brand-strong)" }}>
        依頼者規定{name ? <span style={{ fontWeight: 600 }}>{"（" + name + "）"}</span> : null}
      </div>
      {rows.map(r => (
        <div key={r.key} data-client-rule={r.key} style={{ display: "grid", gridTemplateColumns: "auto minmax(0,1fr)", gap: "0 10px",
          alignItems: "baseline", color: r.sub ? "var(--muted-foreground)" : undefined }}>
          <span style={{ fontSize: "var(--text-caption)", fontWeight: 600, whiteSpace: "nowrap",
            color: r.sub ? "var(--muted-foreground)" : "var(--brand-strong)" }}>{r.label}</span>
          <span style={{ whiteSpace: "pre-wrap", overflowWrap: "anywhere", minWidth: 0 }}>{r.text}</span>
        </div>
      ))}
    </div>
  );
}

/* 案件の依頼者規定を読む(案件詳細・下請手配)。
   ・既定は店の控え(MStore.clientRules ─ rpc_case_detail_context の clientRules)。個別取得が済むまでは出さない。
   ・画面で依頼先を選び直した(clientDbId が控えの orgId と違う)ときだけ、選んだ取引先の行を
     rpc_list_partners(受付の検索と同じ読み取り)から引き直す。古い依頼者の規定を出し続けないため。
     名前だけの変更(clientDbId が空)は保存されない(CaseDetailV25 の依頼先欄)ので、控えのまま。 */
const crByOrg = new Map();   // 取引先ID → 規定(引き直した分だけ。画面を開いている間の控え)
function useCaseClientRules(caseId, clientDbId, clientName, ready) {
  const store = typeof window !== "undefined" ? window.MStore : null;
  const fromCtx = ready && store && typeof store.clientRules === "function" ? store.clientRules(caseId) : undefined;
  const reselected = fromCtx !== undefined && !!clientDbId && (!fromCtx || fromCtx.orgId !== clientDbId);
  const [picked, setPicked] = React.useState(undefined);
  React.useEffect(() => {
    if (!reselected) return undefined;
    if (crByOrg.has(clientDbId)) { setPicked(crByOrg.get(clientDbId)); return undefined; }
    const cloud = window.MarurouCloud;
    if (!cloud || typeof cloud.listPartners !== "function" || !clientName) { setPicked(null); return undefined; }
    let alive = true;
    setPicked(undefined);
    cloud.listPartners({ query: clientName, limit: 20 })
      .then(r => {
        const row = ((r && r.rows) || []).find(x => x && x.id === clientDbId) || null;
        crByOrg.set(clientDbId, row);
        if (alive) setPicked(row);
      })
      .catch(() => { if (alive) setPicked(null); });
    return () => { alive = false; };
  }, [reselected, clientDbId, clientName]);
  if (fromCtx === undefined) return null;
  if (!reselected) return fromCtx;
  return picked && picked.id === clientDbId ? picked : null;
}

/** 案件の帯(案件詳細のヘッダ直下・下請手配)。ready は案件詳細の個別取得が済んだか。 */
function CaseClientRulesBand({ caseId, clientDbId, clientName, ready, fields, showSystem, where, style }) {
  const rules = useCaseClientRules(caseId, clientDbId, clientName, ready !== false);
  return <ClientRulesBand rules={rules} fields={fields} showSystem={showSystem} where={where} style={style} />;
}

Object.assign(window, { ClientRulesBand, CaseClientRulesBand, clientRulesBandRows, CLIENT_RULES_FIELDS });
