// TrackContacts — トラックごとの先方担当(K18-20)。トラック詳細の表示と、TODO 詳細(端末画面)の
// 宛先の初期値が使う部品・規則は、ここ 1 か所に置く。
// ==================================================================
// 値の出どころ(rpc_case_detail_context の trackContacts・0112。案件を開いたときの個別取得):
//   ・業者側(side '業者')        … track_relations(施工会社・担当者あり)。SF の調査/工事の担当者を t17 が取り込む
//   ・保険会社側(side '保険会社') … insurance_claims.insurer_contact_id(SF の保険担当者・t13)
//   店(store.jsx)はメモリにだけ控える(MStore.trackContacts)。案件の state・localStorage には入れない。
//
// 案件単位の関係者(c.parties = case_actors)とは読み分ける:
//   parties は宛先の解決(LINE 0072・contactDbId 0078)と書き込み翻訳(mstore-diff.js の actor.* / contact.log)の元。
//   担当者を parties に足すと、担当者が「案件の関係者」として actor.add に倒れ、LINE の宛先も入れ替わる。
//   ここは parties を読まず、parties へも書かない。TODO 詳細が担当者宛ての連絡を記録するときは、
//   記録は会社(関係者)の行に積み、相手の担当者は記録そのもの(contactDbId)に持たせる(Screens.jsx persistContact)。
//
// 画面から担当者を付け替える操作はまだ無い(読むだけ。K18-20 の報告「形の案」)。

const tcText = v => (typeof v === "string" ? v.trim() : "");
/* トラックの種類 → 宛先の初期値に使う側。保険トラックは保険会社側、ほか(調査・工事)は業者側。 */
const tcSideOf = kind => (kind === "ins" ? "保険会社" : "業者");
const TC_SIDE_LABEL = { "業者": "業者側", "保険会社": "保険会社側" };

/** 案件の中のトラック(画面の局所 id。TRK-… など)から DB の id(tracks.id)を引く。見つからなければ null。
 *  TODO 行(rpc_seed)は trkDbId を持つので、呼び出し側はまずそれを使い、無いときだけこれで引く。 */
function trackDbIdOf(caseId, trkId) {
  const S = typeof window !== "undefined" ? window.MStore : null;
  if (!S || !caseId || !trkId || typeof window.msTracks !== "function") return null;
  const c = S.case(caseId);
  const hit = c ? window.msTracks(c).find(x => x && x.t && x.t.id === trkId) : null;
  return (hit && hit.t.dbId) || null;
}

/** そのトラックの先方担当(店の控え)。個別取得がまだなら undefined、無ければ []。名前の無い行は落とす。 */
function trackContactsOf(caseId, trackDbId) {
  const S = typeof window !== "undefined" ? window.MStore : null;
  if (!S || typeof S.trackContacts !== "function" || !caseId || !trackDbId) return undefined;
  const list = S.trackContacts(caseId, trackDbId);
  return Array.isArray(list) ? list.filter(c => c && tcText(c.name)) : list;
}

/** 宛先の初期値に使う「主」の担当: トラックの種類に合う側の先頭(0112 が新しい順に並べて返す)。無ければ null。 */
function trackContactPrimary(list, kind) {
  if (!Array.isArray(list)) return null;
  const side = tcSideOf(kind);
  return list.find(c => c && c.side === side && tcText(c.name)) || null;
}

/** TODO 詳細(端末画面)の宛先の初期値。優先順:
 *   ① 利用者が選んだタブ ② 督促先 ③ トラックの先方担当 ④ 自社以外のボール ⑤ 先頭の対象者。どれも無ければ null。
 *  ③ は、ボールが自社のとき、またはボールの相手がその担当者の側と同じとき(保険トラックの「保険会社」・
 *  業者ボールの「業者」)だけ。ボールが別の相手(依頼者・居住者など)にあるときは、その相手を先に出す
 *  (担当者は対象者のタブから選べる)。contact.name は呼び出し側で表示名にそろえてから渡す。 */
function deviceDefaultWho({ tab, dunning, ball, contact, targets }) {
  if (tab && tab !== "すべて") return tab;
  if (dunning) return dunning;
  const other = ball && ball !== "自社" ? ball : null;
  const name = contact ? tcText(contact.name) : "";
  if (name && (!other || other === contact.side)) return name;
  if (other) return other;
  const first = Array.isArray(targets) ? targets[0] : null;
  return (first && first.name) || null;
}

/** トラック詳細の「先方担当」の中身。側・担当者名・会社名・役職・電話(PhoneLink。押しても記録はしない)。 */
function TrackContactList({ contacts }) {
  const list = Array.isArray(contacts) ? contacts.filter(c => c && tcText(c.name)) : [];
  if (!list.length) return null;
  return (
    <span data-track-contacts="" style={{ display:"flex", flexDirection:"column", gap:3, minWidth:0 }}>
      {list.map((c, i) => {
        const sub = [tcText(c.orgName), tcText(c.title)].filter(Boolean).join("・");
        return (
          <span key={c.relationId || (c.side + ":" + (c.contactDbId || i))} data-track-contact={c.side}
            style={{ display:"flex", flexWrap:"wrap", alignItems:"baseline", gap:"0 8px", minWidth:0 }}>
            <span style={{ fontSize:"var(--text-caption)", color:"var(--muted-foreground)", whiteSpace:"nowrap" }}>{TC_SIDE_LABEL[c.side] || c.side}</span>
            <b style={{ color:"var(--foreground)" }}>{tcText(c.name)}</b>
            {sub && <span style={{ fontSize:"var(--text-body-sm)", color:"var(--muted-foreground)", overflowWrap:"anywhere" }}>{sub}</span>}
            {c.phone && (typeof PhoneLink === "function"
              ? <PhoneLink phone={c.phone} name={tcText(c.name)} className="mono" />
              : <span className="mono">{c.phone}</span>)}
          </span>
        );
      })}
    </span>
  );
}

/* 案件の外から開く画面(進行詳細 Tracks.jsx)用: 個別取得がまだなら取りに行き、届いたら描き直す。
   案件詳細・TODO 詳細は自分で ensureCaseDetailContext を呼んでいるので、ready を渡して店を読むだけでよい。 */
function useTrackContacts(caseId, trkId, trackDbId) {
  const S = typeof window !== "undefined" ? window.MStore : null;
  const dbId = trackDbId || trackDbIdOf(caseId, trkId);
  const c = S && caseId ? S.case(caseId) : null;
  const caseDbId = c && c.dbId;
  const [, setTick] = React.useState(0);
  // H1(9/25): 案件をサーバの値で差し替えたら(store.jsx caseRev)取り直す。
  const caseRev = S && caseId && typeof S.caseRev === "function" ? S.caseRev(caseId) : 0;
  React.useEffect(() => {
    if (!S || !caseId || !caseDbId || typeof S.ensureCaseDetailContext !== "function") return undefined;
    let alive = true;
    S.ensureCaseDetailContext(caseId, caseDbId).then(() => { if (alive) setTick(n => n + 1); }, () => {});
    return () => { alive = false; };
  }, [caseId, caseDbId, caseRev]);
  const st = S && typeof S.detailContextStatus === "function" ? S.detailContextStatus(caseId) : null;
  if (!st || st.status !== "ready") return undefined;
  return trackContactsOf(caseId, dbId);
}

Object.assign(window, { TrackContactList, trackContactsOf, trackContactPrimary, trackDbIdOf, deviceDefaultWho, useTrackContacts });
