// 橋本商会ポータル — Screens (Home, Intake, Complete, Detail, List)

const { useState: rsState, useEffect: rsEffect, useRef: rsRef, useMemo: rsMemo } = React;

// ═════════════════════════════════════════════════════════════
// HOME / Dashboard
// ═════════════════════════════════════════════════════════════
function HomeScreen({ onNav, onOpenCase, currentUser, variant = "navy" }) {
  const myCases = CASES.filter(c => c.handler === currentUser).slice(0, 3);
  const todayCases = CASES.filter(c => c.status !== "done").slice(0, 4);

  return (
    <div className="screen">
      <AppBar brand variant={variant} sub={`${currentUser} さん  ·  京都拠点`} right={
        <button className="appbar icon-btn"><Ico.bell /></button>
      } />
      <div className="screen-scroll">
        {variant === "brand" ? (
          <div className="section" style={{ marginTop: 4 }}>
            <BrandHero />
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 18 }}>
              <div>
                <div className="tiny">2026.5.24 (日)</div>
                <div className="bold" style={{ fontSize: 16, marginTop: 2 }}>おはようございます、{currentUser}さん</div>
              </div>
              <div style={{ textAlign: "right" }}>
                <div className="tiny">本日受付</div>
                <div className="num bold" style={{ fontSize: 28, lineHeight: 1, color: "var(--accent-strong)" }}>12</div>
              </div>
            </div>
          </div>
        ) : (
          <div className="section">
            <div className="appbar" style={{ padding: "0 0 8px" }}>
              <h1 style={{ fontSize: 22, margin: 0 }}>おはようございます。</h1>
              <div className="sub">5月24日(日)  ·  今日も最高のサービスを。</div>
            </div>
          </div>
        )}

        {/* Today stats */}
        <div className="section">
          <div className="section-head"><h2>今日の状況</h2><span className="more">詳しく</span></div>
          <div className="stat-grid">
            {TODAY_STATS.map((s, i) => (
              <div key={i} className={`stat ${s.accent ? "accent" : ""}`}>
                <div className="label">{s.label}</div>
                <div className="v">{s.value}<span style={{ fontSize: 13, opacity: 0.7, marginLeft: 3 }}>件</span></div>
                <div className="sub">{s.sub}</div>
              </div>
            ))}
          </div>
        </div>

        {/* Quick action — big intake CTA */}
        <div className="section">
          <button className="btn primary lg block" onClick={() => onNav("intake")} style={{ height: 64, fontSize: 16, borderRadius: 16 }}>
            <Ico.mic style={{ marginRight: 4 }} />
            <span>音声で新規受付</span>
            <span className="kbd-helper" style={{ marginLeft: "auto", background: "rgba(255,255,255,0.18)", color: "rgba(255,255,255,0.85)", border: "none" }}>30秒</span>
          </button>
        </div>

        {/* My cases */}
        <div className="section">
          <div className="section-head"><h2>自分宛ての案件</h2><span className="more">{myCases.length}件</span></div>
          <div className="list">
            {myCases.map(c => (
              <button key={c.key} className="list-row" onClick={() => onOpenCase(c.key)}>
                <div className="grow">
                  <div className="title">{c.customer}</div>
                  <div className="meta">
                    <span className="key">{c.key}</span>
                    <span className="sep"></span>
                    <span>{c.model}  {c.plate}</span>
                  </div>
                </div>
                <StatusBadge status={c.status} />
                <Ico.chevR style={{ color: "var(--text-4)", marginLeft: 4 }} />
              </button>
            ))}
          </div>
        </div>

        {/* Today's cases */}
        <div className="section">
          <div className="section-head"><h2>本日対応予定</h2><span className="more" onClick={() => onNav("list")}>すべて見る</span></div>
          <div className="list">
            {todayCases.map(c => (
              <button key={c.key} className="list-row" onClick={() => onOpenCase(c.key)}>
                <div style={{ width: 36, height: 36, borderRadius: 10, background: "var(--surface-3)", display: "grid", placeItems: "center", color: "var(--text-2)" }}>
                  <Ico.car />
                </div>
                <div className="grow">
                  <div className="title">{c.customer}</div>
                  <div className="meta">
                    <span>{c.content.slice(0, 18)}</span>
                  </div>
                </div>
                <div style={{ textAlign: "right" }}>
                  <div className="num" style={{ fontSize: 13, fontWeight: 700 }}>{c.dueDate}</div>
                  <div className="text-xs muted">{c.location}</div>
                </div>
              </button>
            ))}
          </div>
        </div>

        {/* Recent notifications */}
        <div className="section">
          <div className="section-head"><h2>最近の通知</h2></div>
          <div className="col gap-8">
            {RECENT_NOTIFS.map((n, i) => (
              <div key={i} className="notif">
                <div className="ico-wrap">
                  {n.kind === "chat" ? <Ico.chat /> : <Ico.cal />}
                </div>
                <div style={{ flex: 1 }}>
                  <div className="label">{n.text}</div>
                  <div className="meta">
                    <span className="mono" style={{ fontSize: 10 }}>{n.caseKey}</span> · {n.time}
                  </div>
                </div>
                <div className="check"><Ico.checkSmall /></div>
              </div>
            ))}
          </div>
        </div>

        <div style={{ height: 24 }} />
      </div>
      <TabBar active="home" onNav={onNav} />
    </div>
  );
}

// ═════════════════════════════════════════════════════════════
// INTAKE FORM
// ═════════════════════════════════════════════════════════════
function IntakeScreen({ onNav, onSubmit, variant = "navy" }) {
  const [stage, setStage] = rsState("idle"); // idle | recording | structuring | review
  const [transcript, setTranscript] = rsState("");
  const [fields, setFields] = rsState({
    customer: { value: "", confidence: 0, filled: false },
    model: { value: "", confidence: 0, filled: false },
    plate: { value: "", confidence: 0, filled: false },
    content: { value: "", confidence: 0, filled: false },
    dueDate: { value: "", confidence: 0, filled: false },
    location: { value: "京都", confidence: 1, filled: true },
    sections: { value: [], confidence: 0, filled: false },
    division: { value: "", confidence: 0, filled: false },
    slip: { value: "", confidence: 0, filled: false },
  });
  const [animKey, setAnimKey] = rsState(0);
  const [recordedFor, setRecordedFor] = rsState(0);
  const recordTimer = rsRef(null);

  const startRecord = () => {
    setStage("recording");
    setTranscript("");
    setRecordedFor(0);
    recordTimer.current = setInterval(() => setRecordedFor(r => r + 0.1), 100);
    // Simulate transcript appearing
    const target = STRUCTURE_DEMO.transcript;
    let i = 0;
    const txTimer = setInterval(() => {
      i += 2;
      setTranscript(target.slice(0, i));
      if (i >= target.length) clearInterval(txTimer);
    }, 80);
  };

  const stopRecord = () => {
    if (recordTimer.current) clearInterval(recordTimer.current);
    setStage("structuring");
    // After short delay, fill fields one-by-one
    const order = ["customer", "model", "plate", "content", "dueDate", "location", "sections", "division"];
    setTimeout(() => {
      order.forEach((key, idx) => {
        setTimeout(() => {
          setFields(f => ({
            ...f,
            [key]: { value: STRUCTURE_DEMO.fields[key].value, confidence: STRUCTURE_DEMO.fields[key].confidence, filled: true },
          }));
          setAnimKey(k => k + 1);
          if (idx === order.length - 1) setStage("review");
        }, idx * 220);
      });
    }, 600);
  };

  const reset = () => {
    setStage("idle");
    setTranscript("");
    setFields({
      customer: { value: "", confidence: 0, filled: false },
      model: { value: "", confidence: 0, filled: false },
      plate: { value: "", confidence: 0, filled: false },
      content: { value: "", confidence: 0, filled: false },
      dueDate: { value: "", confidence: 0, filled: false },
      location: { value: "京都", confidence: 1, filled: true },
      sections: { value: [], confidence: 0, filled: false },
      division: { value: "", confidence: 0, filled: false },
      slip: { value: "", confidence: 0, filled: false },
    });
  };

  // Sheet states for selectors (常にnullから開始 — 入り口で前回ステートが残らない保険)
  const [openSheet, setOpenSheet] = rsState(null);
  rsEffect(() => { setOpenSheet(null); }, []);

  const setField = (key, value, confidence = 1) => {
    setFields(f => ({ ...f, [key]: { value, confidence, filled: true } }));
  };

  const canSubmit = fields.customer.filled && fields.plate.filled && fields.model.filled && fields.content.filled && fields.sections.value.length > 0 && fields.slip.filled && fields.division.filled;

  return (
    <div className="screen">
      <AppBar
        variant={variant}
        title="新規受付"
        sub={stage === "idle" ? "音声入力で30秒受付" : stage === "recording" ? "録音中…話し終わったら■ボタン" : stage === "structuring" ? "自動構造化しています…" : "内容を確認して送信"}
        big
        left={<button className="appbar icon-btn" onClick={() => onNav("home")}><Ico.back /></button>}
        right={stage !== "idle" ? <button className="appbar icon-btn" onClick={reset}><Ico.reset /></button> : <button className="appbar icon-btn"><Ico.more /></button>}
      />

      <div className="screen-scroll">
        {/* Voice input area */}
        <div className="section">
          <div className="card" style={{ background: stage === "recording" ? "var(--surface)" : "var(--surface-2)", borderColor: stage === "recording" ? "oklch(0.85 0.10 28)" : "var(--border)" }}>
            <div className="mic-wrap">
              <MicButton recording={stage === "recording"} onClick={stage === "recording" ? stopRecord : stage === "idle" ? startRecord : undefined} />
              <Waveform active={stage === "recording"} />
              {stage === "idle" && (
                <div className="mic-hint">
                  マイクをタップして話してください<br/>
                  <strong>例:</strong>「徳商奈良、エルフ4491、3ヶ月点検、5月24日納車希望」
                </div>
              )}
              {stage === "recording" && (
                <div className="mic-hint">
                  <span className="num bold" style={{ color: "var(--danger)" }}>{recordedFor.toFixed(1)}s</span>  録音中
                </div>
              )}
              {stage !== "idle" && transcript && (
                <div style={{ background: "var(--surface-3)", borderRadius: 12, padding: 12, fontSize: 14, lineHeight: 1.5, color: "var(--text-2)", width: "100%" }}>
                  <div className="tiny" style={{ marginBottom: 4 }}>音声認識結果</div>
                  {transcript}{stage === "recording" && <span style={{ animation: "blink 1s infinite" }}>|</span>}
                </div>
              )}
            </div>
          </div>
        </div>

        {/* Structured fields */}
        {stage !== "idle" && (
          <div className="section">
            <div className="section-head">
              <h2>抽出された案件情報</h2>
              {stage === "structuring" && <StructuringDots />}
              {stage === "review" && <span className="text-xs" style={{ color: "var(--success)", fontWeight: 700 }}>✓ 完了</span>}
            </div>

            {stage === "review" && <StructureSummary fields={fields} />}

            <div className="col gap-8" style={{ marginTop: stage === "review" ? 12 : 0 }}>
              <Field
                label="顧客名"
                required
                value={fields.customer.value}
                animateKey={fields.customer.filled ? `cust-${animKey}` : null}
                low={fields.customer.filled && fields.customer.confidence < 0.8}
                confidence={fields.customer.filled ? fields.customer.confidence : null}
                onClick={() => setOpenSheet("customer")}
              />
              <Field
                label="車種・車名"
                required
                value={fields.model.value}
                animateKey={fields.model.filled ? `mdl-${animKey}` : null}
                low={fields.model.filled && fields.model.confidence < 0.8}
                confidence={fields.model.filled ? fields.model.confidence : null}
                onClick={() => setOpenSheet("model")}
              />
              <Field
                label="登録番号 (ナンバープレート)"
                required
                value={fields.plate.value}
                animateKey={fields.plate.filled ? `pl-${animKey}` : null}
                low={fields.plate.filled && fields.plate.confidence < 0.8}
                confidence={fields.plate.filled ? fields.plate.confidence : null}
                onClick={() => setOpenSheet("plate")}
              />
              <Field
                label="依頼内容"
                required
                multiline
                value={fields.content.value}
                animateKey={fields.content.filled ? `con-${animKey}` : null}
                low={fields.content.filled && fields.content.confidence < 0.8}
                confidence={fields.content.filled ? fields.content.confidence : null}
                onClick={() => setOpenSheet("content")}
              />

              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
                <Field
                  label="納車・完了希望日"
                  value={fields.dueDate.value}
                  animateKey={fields.dueDate.filled ? `dd-${animKey}` : null}
                  confidence={fields.dueDate.filled ? fields.dueDate.confidence : null}
                  onClick={() => setOpenSheet("date")}
                />
                <Field
                  label="拠点"
                  required
                  value={fields.location.value}
                  onClick={() => setOpenSheet("location")}
                />
              </div>

              {/* Sections — multi select */}
              <Field
                label="依頼先セクション (複数選択可)"
                required
                low={fields.sections.filled && fields.sections.confidence < 0.8}
                confidence={fields.sections.filled ? fields.sections.confidence : null}
                animateKey={fields.sections.filled ? `sec-${animKey}` : null}
              >
                <div style={{ marginTop: 8 }}>
                  <ChipMulti
                    options={SECTIONS}
                    value={fields.sections.value}
                    onChange={(v) => setField("sections", v, 1)}
                  />
                </div>
              </Field>

              {/* Slip type */}
              <Field label="伝票種類" required animateKey={fields.slip.filled ? `slip-${animKey}` : null}>
                <div style={{ marginTop: 8 }}>
                  <PillRadio
                    options={SLIP_TYPES}
                    value={fields.slip.value}
                    onChange={(v) => setField("slip", v, 1)}
                  />
                </div>
              </Field>

              {/* Division */}
              <Field
                label="事業部"
                required
                low={fields.division.filled && fields.division.confidence < 0.8}
                confidence={fields.division.filled ? fields.division.confidence : null}
                animateKey={fields.division.filled ? `div-${animKey}` : null}
              >
                <div style={{ marginTop: 8 }}>
                  <PillRadio
                    options={DIVISIONS}
                    value={fields.division.value}
                    onChange={(v) => setField("division", v, 1)}
                  />
                </div>
              </Field>

              {/* Advanced — collapsed */}
              <details className="card flat" style={{ padding: 0 }}>
                <summary style={{ padding: 14, fontSize: 13, fontWeight: 600, color: "var(--text-2)", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "space-between", listStyle: "none" }}>
                  <span>その他の項目 (入金・備考)</span>
                  <Ico.chevD />
                </summary>
                <div className="col gap-8" style={{ padding: "0 14px 14px" }}>
                  <Field label="入金タイミング" value={fields.payTiming?.value || ""} onClick={() => setOpenSheet("payTiming")} />
                  <Field label="入金方法" value={fields.payMethod?.value || ""} onClick={() => setOpenSheet("payMethod")} />
                </div>
              </details>
            </div>
          </div>
        )}

        <div style={{ height: 12 }} />
      </div>

      {/* Submit CTA */}
      {stage !== "idle" && (
        <div className="sticky-cta">
          <button
            className="btn primary lg block"
            disabled={!canSubmit}
            style={{ opacity: canSubmit ? 1 : 0.5 }}
            onClick={() => canSubmit && onSubmit(fields)}
          >
            <Ico.check />
            受付を送信する
          </button>
        </div>
      )}

      {/* Sheets */}
      <Sheet open={openSheet === "location"} onClose={() => setOpenSheet(null)} title="拠点を選択">
        <div className="col gap-8">
          {LOCATIONS.map(l => (
            <button key={l} className="list-row" onClick={() => { setField("location", l, 1); setOpenSheet(null); }} style={{ borderRadius: 12, border: "1px solid var(--border)" }}>
              <Ico.pin style={{ color: "var(--text-3)" }} />
              <div className="grow"><div className="title">{l}</div></div>
              {fields.location.value === l && <Ico.check style={{ color: "var(--primary)" }} />}
            </button>
          ))}
        </div>
      </Sheet>

      <Sheet open={openSheet === "customer"} onClose={() => setOpenSheet(null)} title="顧客名を編集">
        {openSheet === "customer" ? (
          <CustomerSearchPicker
            initial={fields.customer.value}
            onPick={(name) => { setField("customer", name, 1); setOpenSheet(null); }}
          />
        ) : null}
      </Sheet>

      <Sheet open={openSheet === "model"} onClose={() => setOpenSheet(null)} title="車種・車名を編集">
        {openSheet === "model" ? (
          <VehicleSearchPicker
            initialPlate={fields.plate.value}
            initialModel={fields.model.value}
            customerName={fields.customer.value}
            mode="model"
            onPick={({ model, plate }) => {
              if (model) setField("model", model, 1);
              if (plate) setField("plate", plate, 1);
              setOpenSheet(null);
            }}
          />
        ) : null}
      </Sheet>

      <Sheet open={openSheet === "plate"} onClose={() => setOpenSheet(null)} title="登録番号を編集">
        {openSheet === "plate" ? (
          <VehicleSearchPicker
            initialPlate={fields.plate.value}
            initialModel={fields.model.value}
            customerName={fields.customer.value}
            mode="plate"
            onPick={({ model, plate }) => {
              if (plate) setField("plate", plate, 1);
              if (model) setField("model", model, 1);
              setOpenSheet(null);
            }}
          />
        ) : null}
      </Sheet>

      <Sheet open={openSheet === "content"} onClose={() => setOpenSheet(null)} title="依頼内容を編集">
        <Field label="依頼内容" required>
          <textarea defaultValue={fields.content.value} onChange={e => setField("content", e.target.value, 1)} rows={4} placeholder="依頼内容を入力" />
        </Field>
      </Sheet>

      <Sheet open={openSheet === "date"} onClose={() => setOpenSheet(null)} title="納車・完了希望日">
        <DemoCalendar value={fields.dueDate.value} onChange={(d) => { setField("dueDate", d, 1); setOpenSheet(null); }} />
      </Sheet>
    </div>
  );
}

// Tiny demo calendar
function DemoCalendar({ value, onChange }) {
  const days = Array.from({ length: 31 }, (_, i) => i + 1);
  const sel = value ? parseInt(value.split("-").pop()) : null;
  return (
    <div>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "0 4px 12px" }}>
        <div className="bold">2026年5月</div>
        <div className="row">
          <button className="appbar icon-btn" style={{ width: 32, height: 32 }}><Ico.back /></button>
          <button className="appbar icon-btn" style={{ width: 32, height: 32 }}><Ico.chevR /></button>
        </div>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(7, 1fr)", gap: 4, padding: 4 }}>
        {["日","月","火","水","木","金","土"].map(d => (
          <div key={d} className="tiny" style={{ textAlign: "center", padding: "4px 0" }}>{d}</div>
        ))}
        {/* offset for May 1 = Friday */}
        {Array.from({ length: 5 }, (_, i) => <div key={"o" + i} />)}
        {days.map(d => {
          const isSel = d === sel;
          const isToday = d === 24;
          return (
            <button key={d} onClick={() => onChange(`2026-05-${String(d).padStart(2, "0")}`)}
              style={{
                aspectRatio: "1",
                borderRadius: 10,
                background: isSel ? "var(--primary)" : isToday ? "var(--primary-soft)" : "transparent",
                color: isSel ? "var(--on-primary)" : isToday ? "var(--primary)" : "var(--text)",
                fontWeight: isSel || isToday ? 700 : 500,
                fontFamily: "var(--font-num)",
                fontSize: 14,
              }}>{d}</button>
          );
        })}
      </div>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════
// INTAKE COMPLETE
// ═════════════════════════════════════════════════════════════
function CompleteScreen({ caseKey, fields, onNav, onShowToast, onOpenCase, variant = "navy" }) {
  const customer = fields?.customer?.value || "—";
  const model = fields?.model?.value || "";
  const plate = fields?.plate?.value || "";
  const vehicle = [model, plate].filter(Boolean).join(" / ") || "—";
  const content = fields?.content?.value || "—";
  const sections = fields?.sections?.value || [];
  const location = fields?.location?.value || "京都";

  const [notifProgress, setNotifProgress] = rsState(0); // 0 → 4, count of completed steps
  rsEffect(() => {
    const order = [1, 2, 3, 4];
    order.forEach((n, i) => {
      setTimeout(() => setNotifProgress(p => Math.max(p, n)), 400 + i * 550);
    });
  }, []);

  return (
    <div className="screen">
      <AppBar
        variant={variant}
        title=""
        left={<button className="appbar icon-btn" onClick={() => onNav("home")}><Ico.x /></button>}
        right={<button className="appbar icon-btn"><Ico.more /></button>}
      />
      <div className="screen-scroll">
        {/* Big success */}
        <div style={{ display: "flex", flexDirection: "column", alignItems: "center", padding: "20px 24px 24px", textAlign: "center" }}>
          <div style={{
            width: 64, height: 64, borderRadius: 999,
            background: "var(--success)",
            display: "grid", placeItems: "center", color: "white",
            boxShadow: "0 8px 24px oklch(0.55 0.13 155 / 0.30), 0 0 0 8px var(--success-soft)",
            marginBottom: 14,
            animation: "pop 0.4s ease",
          }}>
            <Ico.check style={{ width: 32, height: 32 }} />
          </div>
          <div style={{ fontSize: 22, fontWeight: 700, marginBottom: 4 }}>受付完了</div>
          <div className="muted text-sm">案件キーが発行されました · {new Date().toLocaleTimeString("ja-JP", { hour: "2-digit", minute: "2-digit" })}</div>
        </div>

        {/* Case key + QR card */}
        <div className="section">
          <div className="card" style={{ padding: 18, background: "var(--surface)", borderColor: "var(--border-strong)" }}>
            <div style={{ display: "flex", gap: 16, alignItems: "center" }}>
              <div style={{ flex: 1 }}>
                <CaseKey value={caseKey} size="lg" onCopy={() => onShowToast("コピーしました")} />
              </div>
              <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 4 }}>
                <FakeQR value={caseKey} size={76} />
                <div className="tiny" style={{ fontSize: 9 }}>QR で開く</div>
              </div>
            </div>

            {/* GATCH + 指示書 numbers — issued after intake */}
            <div style={{
              marginTop: 14, paddingTop: 14, borderTop: "1px solid var(--divider)",
              display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14,
            }}>
              <div>
                <div className="tiny" style={{ fontSize: 9, display: "flex", alignItems: "center", gap: 4 }}>
                  GATCH 受付番号
                  <span style={{ width: 5, height: 5, borderRadius: 99, background: "var(--success)", animation: "pop 0.4s ease both" }} />
                </div>
                <div className="mono bold" style={{ fontSize: 13, marginTop: 3, letterSpacing: 0.02 }}
                     onClick={() => onShowToast("コピーしました")}>
                  G-26-05241-{(parseInt(caseKey.split("-")[1]) + 100).toString().padStart(4, "0")}
                </div>
              </div>
              <div>
                <div className="tiny" style={{ fontSize: 9 }}>指示書番号</div>
                <div className="mono" style={{ fontSize: 13, marginTop: 3, color: "var(--text-4)", display: "flex", alignItems: "center", gap: 4 }}>
                  発行待ち
                  <span style={{
                    width: 12, height: 12, borderRadius: 999,
                    border: "2px solid var(--border-strong)", borderTopColor: "transparent",
                    animation: "spin 0.8s linear infinite", display: "inline-block",
                  }} />
                </div>
              </div>
            </div>

            <div style={{ display: "flex", gap: 8, marginTop: 14, paddingTop: 14, borderTop: "1px solid var(--divider)" }}>
              <button className="btn" style={{ flex: 1, height: 38, fontSize: 12 }} onClick={() => onShowToast("コピーしました")}>
                <Ico.copy style={{ width: 14, height: 14 }} /> コピー
              </button>
              <button className="btn" style={{ flex: 1, height: 38, fontSize: 12 }}>
                <Ico.chat style={{ width: 14, height: 14 }} /> 共有
              </button>
              <button className="btn" style={{ flex: 1, height: 38, fontSize: 12 }}>
                <Ico.list style={{ width: 14, height: 14 }} /> 伝票
              </button>
            </div>
          </div>
        </div>

        {/* Submission summary */}
        <div className="section">
          <div className="section-head"><h2>受付内容</h2></div>
          <div className="card" style={{ padding: 0 }}>
            <div style={{ padding: "14px 16px", borderBottom: "1px solid var(--divider)" }}>
              <div className="tiny" style={{ marginBottom: 4 }}>顧客 / 車両</div>
              <div className="bold">{customer}</div>
              <div className="text-sm muted">{vehicle}</div>
            </div>
            <div style={{ padding: "14px 16px", borderBottom: "1px solid var(--divider)" }}>
              <div className="tiny" style={{ marginBottom: 4 }}>依頼内容</div>
              <div>{content}</div>
            </div>
            <div style={{ padding: "14px 16px", display: "flex", justifyContent: "space-between", gap: 12 }}>
              <div style={{ flex: 1 }}>
                <div className="tiny" style={{ marginBottom: 4 }}>依頼先</div>
                <div className="row gap-4" style={{ flexWrap: "wrap" }}>
                  {sections.map(s => <span key={s} className="chip on" style={{ height: 26, fontSize: 11 }}>{s}</span>)}
                </div>
              </div>
              <div style={{ textAlign: "right" }}>
                <div className="tiny" style={{ marginBottom: 4 }}>拠点</div>
                <div className="bold">{location}</div>
              </div>
            </div>
          </div>
        </div>

        {/* Notification status — sequential */}
        <div className="section">
          <div className="section-head">
            <h2>通知の送信状況</h2>
            <span className="text-xs" style={{ color: notifProgress >= 4 ? "var(--success)" : "var(--text-3)", fontWeight: 700 }}>
              {notifProgress >= 4 ? "✓ すべて完了" : `${notifProgress} / 4`}
            </span>
          </div>
          <div className="col gap-8">
            <NotifAnim done={notifProgress >= 1} icon="chat" label="Google Chat「整備スペース」" meta="自動メッセージ送信" />
            <NotifAnim done={notifProgress >= 2} icon="cal" label={`Google カレンダー「${location}」`} meta="5/24 10:00 予定を追加" />
            <NotifAnim done={notifProgress >= 3} icon="list" label="JOOTO / GATCH" meta="案件カードを作成 / 担当 三浦" />
            <NotifAnim done={notifProgress >= 4} icon="phone" label="顧客への確認メール" meta="徳商奈良(株) 田中様 宛て" />
          </div>
        </div>

        <div style={{ height: 24 }} />
      </div>

      {/* Actions */}
      <div className="sticky-cta col gap-8" style={{ display: "flex", flexDirection: "column" }}>
        <button className="btn primary lg block" onClick={() => onOpenCase(caseKey)}>
          案件詳細を見る <Ico.arrowR />
        </button>
        <button className="btn block" onClick={() => onNav("intake")}>
          <Ico.plus style={{ width: 18, height: 18 }} /> もう一件受け付ける
        </button>
      </div>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════
// CASE DETAIL
// ═════════════════════════════════════════════════════════════
function CaseDetailScreen({ caseKey, onNav, onShowToast, variant = "navy" }) {
  const c = CASES.find(x => x.key === caseKey) || CASES[0];
  const purchases = PURCHASES.filter(p => p.caseKey === c.key);
  const purchaseTotal = purchases.reduce((sum, p) => sum + p.amount * p.qty, 0);
  const [purchaseSheet, setPurchaseSheet] = rsState(false);
  const [openPurchase, setOpenPurchase] = rsState(null);

  return (
    <div className="screen">
      <AppBar
        variant={variant}
        title={c.customer}
        sub={`${c.model} ・ ${c.plate}`}
        left={<button className="appbar icon-btn" onClick={() => onNav("home")}><Ico.back /></button>}
        right={<button className="appbar icon-btn"><Ico.more /></button>}
      />
      <div className="screen-scroll">
        {/* Numbers panel — case key + GATCH + 指示書 */}
        <div className="section">
          <div className="card" style={{ background: "var(--surface)", padding: 0, overflow: "hidden" }}>
            <div style={{ display: "flex", alignItems: "center", padding: "14px 16px", justifyContent: "space-between" }}>
              <div style={{ flex: 1 }}>
                <div className="tiny">案件キー</div>
                <div className="mono bold" style={{ fontSize: 18, letterSpacing: 0.04, marginTop: 2 }}
                     onClick={() => onShowToast("コピーしました")}>{c.key}</div>
                <div className="text-xs muted" style={{ marginTop: 4 }}>受付: {c.receivedAt} · 担当 {c.handler}</div>
              </div>
              <StatusBadge status={c.status} />
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", borderTop: "1px solid var(--divider)" }}>
              <div style={{ padding: "10px 16px", borderRight: "1px solid var(--divider)" }}
                   onClick={() => onShowToast("GATCH 受付番号をコピー")}>
                <div className="tiny" style={{ fontSize: 9 }}>GATCH 受付番号</div>
                <div className="mono" style={{ fontSize: 13, fontWeight: 600, marginTop: 2 }}>{c.gatchKey || "—"}</div>
              </div>
              <div style={{ padding: "10px 16px" }}
                   onClick={() => onShowToast("指示書番号をコピー")}>
                <div className="tiny" style={{ fontSize: 9 }}>指示書番号</div>
                <div className="mono" style={{ fontSize: 13, fontWeight: 600, marginTop: 2, color: c.instructionNo ? "var(--text)" : "var(--text-4)" }}>
                  {c.instructionNo || "発行待ち"}
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* Stepper */}
        <div className="section">
          <div className="card">
            <StatusStepper current={c.status} />
          </div>
        </div>

        {/* Request details */}
        <div className="section">
          <div className="section-head"><h2>依頼内容</h2><button className="more"><Ico.edit /></button></div>
          <div className="card" style={{ padding: 0 }}>
            <DetailRow label="顧客" value={c.customer} />
            <DetailRow label="車種・車名" value={c.model} />
            <DetailRow label="登録番号" value={c.plate} />
            <DetailRow label="内容" value={c.content} />
            <DetailRow label="依頼先" custom={
              <div className="row gap-4" style={{ flexWrap: "wrap" }}>
                {c.sections.map(s => <span key={s} className="chip on" style={{ height: 26, fontSize: 11 }}>{s}</span>)}
              </div>
            } />
            <DetailRow label="伝票種類" value={c.slip} />
            <DetailRow label="事業部" value={c.division} />
            <DetailRow label="納車・完了希望" value={c.dueDate} />
            <DetailRow label="拠点" value={c.location} last />
          </div>
        </div>

        {/* Purchase reports — 仕入報告 */}
        <div className="section">
          <div className="section-head">
            <h2>仕入報告</h2>
            <span className="more" onClick={() => setPurchaseSheet(true)}>+ 報告を追加</span>
          </div>
          {purchases.length > 0 && (
            <div className="card" style={{ padding: 12, marginBottom: 8, display: "flex", justifyContent: "space-between", alignItems: "center", background: "var(--primary-soft)", borderColor: "transparent" }}>
              <div>
                <div className="tiny" style={{ fontSize: 9 }}>仕入合計 ({purchases.length}件)</div>
                <div className="num bold" style={{ fontSize: 20, marginTop: 2 }}>¥{purchaseTotal.toLocaleString()}</div>
              </div>
              <div style={{ textAlign: "right" }}>
                <div className="tiny" style={{ fontSize: 9 }}>GATCH反映</div>
                <div className="num bold" style={{ fontSize: 13, marginTop: 2 }}>
                  {purchases.filter(p => p.status === "posted").length} / {purchases.length} 件
                </div>
              </div>
            </div>
          )}
          {purchases.length === 0 ? (
            <button className="card" onClick={() => setPurchaseSheet(true)}
              style={{ width: "100%", textAlign: "left", background: "var(--surface-2)", borderStyle: "dashed", padding: 18, display: "flex", alignItems: "center", gap: 12 }}>
              <div style={{ width: 36, height: 36, borderRadius: 10, background: "var(--surface)", border: "1px solid var(--border)", display: "grid", placeItems: "center", color: "var(--text-3)" }}>
                <Ico.plus />
              </div>
              <div style={{ flex: 1 }}>
                <div className="bold text-sm">この案件の仕入を報告する</div>
                <div className="text-xs muted">部品・工具・外注などを記録</div>
              </div>
            </button>
          ) : (
            <div className="list">
              {purchases.map(p => (
                <button key={p.id} className="list-row" onClick={() => setOpenPurchase(p)}>
                  <div style={{ width: 36, height: 36, borderRadius: 10, background: "var(--surface-3)", display: "grid", placeItems: "center", color: "var(--text-2)", flexShrink: 0 }}>
                    {p.category === "部品" ? "🔧" : p.category === "工具" ? "🛠" : p.category === "消耗品" ? "🛢" : p.category === "外注作業" ? "🤝" : "•"}
                  </div>
                  <div className="grow">
                    <div className="row gap-4" style={{ marginBottom: 2 }}>
                      <PurchaseBadge status={p.status} />
                      <span className="text-xs muted">{p.supplier}</span>
                    </div>
                    <div className="title" style={{ fontSize: 13 }}>{p.item}</div>
                    <div className="meta">
                      <span className="mono" style={{ fontWeight: 600 }}>¥{p.amount.toLocaleString()}</span>
                      {p.qty > 1 && <span> × {p.qty}</span>}
                      <span className="sep"></span>
                      <span>{p.reportedBy} · {p.reportedAt}</span>
                      {p.hasReceipt && <><span className="sep"></span><span>📎</span></>}
                    </div>
                  </div>
                  <Ico.chevR style={{ color: "var(--text-4)", flexShrink: 0 }} />
                </button>
              ))}
              <button className="list-row" onClick={() => setPurchaseSheet(true)}
                style={{ color: "var(--accent-fg, var(--primary))", justifyContent: "center", gap: 6, fontWeight: 600 }}>
                <Ico.plus style={{ width: 18, height: 18 }} /> 仕入を報告する
              </button>
            </div>
          )}
        </div>

        {/* Calendar linkage */}
        <div className="section">
          <div className="section-head"><h2>カレンダー連携</h2><span className="more">Google Cal で開く</span></div>
          <div className="card" style={{ padding: 0 }}>
            <div style={{ display: "flex", padding: "14px 16px", gap: 12, borderBottom: "1px solid var(--divider)" }}>
              <div style={{ width: 48, textAlign: "center" }}>
                <div className="tiny" style={{ color: "var(--danger)" }}>5月</div>
                <div className="num" style={{ fontSize: 24, fontWeight: 700, lineHeight: 1 }}>24</div>
                <div className="text-xs muted">日</div>
              </div>
              <div style={{ flex: 1 }}>
                <div className="bold">納車予定 — {c.location}</div>
                <div className="text-sm muted">10:00 - 11:00 · 整備セクション</div>
                <div className="text-xs" style={{ color: "var(--success)", marginTop: 4 }}>✓ カレンダー登録済</div>
              </div>
            </div>
            <div style={{ padding: "14px 16px", display: "flex", gap: 12 }}>
              <div style={{ width: 48, textAlign: "center" }}>
                <div className="tiny muted">5月</div>
                <div className="num" style={{ fontSize: 24, fontWeight: 700, lineHeight: 1, color: "var(--text-3)" }}>23</div>
                <div className="text-xs muted">土</div>
              </div>
              <div style={{ flex: 1 }}>
                <div>事前点検 — 自社</div>
                <div className="text-sm muted">14:00 - 15:00</div>
              </div>
            </div>
          </div>
        </div>

        {/* Sales (Phase E placeholder) */}
        <div className="section">
          <div className="section-head"><h2>売上</h2><span className="badge cancel"><span className="dot"></span>Phase E</span></div>
          <div className="card" style={{ background: "var(--surface-2)", borderStyle: "dashed", textAlign: "center", padding: 20 }}>
            <div className="muted text-sm">予定売上と実績の照合は<br/>Phase E で連携予定です</div>
          </div>
        </div>

        {/* Notification history */}
        <div className="section">
          <div className="section-head"><h2>通知履歴</h2></div>
          <div className="col gap-8">
            <NotifLine icon="chat" label="Google Chat 整備スペース" time={c.receivedAt} />
            <NotifLine icon="cal" label={`Google カレンダー(${c.location})`} time={c.receivedAt} />
            {c.status !== "intake" && <NotifLine icon="chat" label="Google Chat 集配スペース" time="昨日 17:01" />}
          </div>
        </div>

        <div style={{ height: 24 }} />
      </div>

      {/* Footer actions */}
      <div className="sticky-cta">
        <div className="row gap-8">
          <button className="btn" style={{ flex: 1 }}><Ico.edit style={{ width: 18, height: 18 }} /> 編集</button>
          <button className="btn primary" style={{ flex: 2 }}><Ico.check /> 完了にする</button>
        </div>
      </div>

      {/* Purchase report sheet */}
      <PurchaseReportSheet open={purchaseSheet} onClose={() => setPurchaseSheet(false)} caseRef={c} onShowToast={onShowToast} />
      <PurchaseDetailSheet purchase={openPurchase} onClose={() => setOpenPurchase(null)} />
    </div>
  );
}

function DetailRow({ label, value, sub, custom, last }) {
  return (
    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", padding: "12px 16px", borderBottom: last ? "none" : "1px solid var(--divider)", gap: 12 }}>
      <div className="tiny" style={{ minWidth: 80, paddingTop: 2 }}>{label}</div>
      <div style={{ textAlign: "right", flex: 1 }}>
        {custom ? custom : (
          <>
            <div className="bold" style={{ fontSize: 14 }}>{value}</div>
            {sub && <div className="text-xs muted" style={{ marginTop: 2 }}>{sub}</div>}
          </>
        )}
      </div>
    </div>
  );
}

function NotifLine({ icon, label, time }) {
  return (
    <div className="notif">
      <div className="ico-wrap">{icon === "chat" ? <Ico.chat /> : <Ico.cal />}</div>
      <div style={{ flex: 1 }}>
        <div className="label">{label}</div>
        <div className="meta">{time}</div>
      </div>
      <div className="check"><Ico.checkSmall /></div>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════
// CASE LIST
// ═════════════════════════════════════════════════════════════
function CaseListScreen({ onNav, onOpenCase, variant = "navy" }) {
  const [filter, setFilter] = rsState("all");
  const [query, setQuery] = rsState("");

  const filters = [
    { id: "all", label: "すべて", count: CASES.length },
    { id: "today", label: "本日", count: 4 },
    { id: "mine", label: "自分宛て", count: 3 },
    { id: "intake", label: "受付", count: 2 },
    { id: "progress", label: "整備中", count: 2 },
    { id: "delivery", label: "集配", count: 1 },
    { id: "done", label: "完了", count: 1 },
  ];

  const list = CASES.filter(c => {
    if (filter === "all") return true;
    if (filter === "mine") return c.handler === "三浦";
    if (filter === "today") return c.key.startsWith("20260524");
    return c.status === filter;
  }).filter(c => {
    if (!query) return true;
    const q = query.toLowerCase();
    return c.customer.toLowerCase().includes(q) || c.key.includes(q) || c.model.toLowerCase().includes(q) || c.plate.toLowerCase().includes(q);
  });

  return (
    <div className="screen">
      <AppBar
        variant={variant}
        title="案件一覧"
        big
        left={<button className="appbar icon-btn" onClick={() => onNav("home")}><Ico.back /></button>}
        right={<button className="appbar icon-btn"><Ico.filter /></button>}
      />

      {/* Search bar */}
      <div style={{ padding: "0 16px 8px" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8, background: "var(--surface-3)", borderRadius: 12, padding: "10px 12px" }}>
          <Ico.search style={{ color: "var(--text-3)" }} />
          <input
            type="text"
            placeholder="顧客名 / 案件キー / 車両ナンバー"
            value={query}
            onChange={e => setQuery(e.target.value)}
            style={{ flex: 1, border: "none", outline: "none", background: "transparent", fontSize: 14 }}
          />
          {query && <button onClick={() => setQuery("")}><Ico.x /></button>}
        </div>
      </div>

      {/* Filter chips */}
      <div className="filter-row">
        {filters.map(f => (
          <button key={f.id} className={`filter-chip ${filter === f.id ? "on" : ""}`} onClick={() => setFilter(f.id)}>
            {f.label} <span style={{ opacity: 0.7, fontFamily: "var(--font-num)" }}>{f.count}</span>
          </button>
        ))}
      </div>

      <div className="screen-scroll">
        <div className="section" style={{ marginTop: 4 }}>
          {list.length === 0 ? (
            <div className="card" style={{ textAlign: "center", padding: 24 }}>
              <div className="muted">該当する案件はありません</div>
            </div>
          ) : (
            <div className="list">
              {list.map(c => (
                <button key={c.key} className="list-row" onClick={() => onOpenCase(c.key)}>
                  <div className="grow">
                    <div className="row" style={{ gap: 8, marginBottom: 2 }}>
                      <span className="key mono">{c.key}</span>
                      <StatusBadge status={c.status} />
                    </div>
                    <div className="title">{c.customer}</div>
                    <div className="meta">
                      <span>{c.model}  {c.plate}</span>
                      <span className="sep"></span>
                      <span>{c.content.slice(0, 18)}{c.content.length > 18 ? "…" : ""}</span>
                    </div>
                  </div>
                  <div style={{ textAlign: "right", flexShrink: 0 }}>
                    <div className="num bold" style={{ fontSize: 14 }}>{c.dueDate}</div>
                    <div className="text-xs muted">{c.location}</div>
                  </div>
                </button>
              ))}
            </div>
          )}
        </div>
        <div style={{ height: 24 }} />
      </div>

      <TabBar active="list" onNav={onNav} />
    </div>
  );
}

// ============================================================
// GATCH マスタサジェスト ピッカー (実 API 連携)
// bridge_master_api.py (port 8788) を Cloudflare Tunnel 経由で叩く
// ============================================================

function _useDebouncedFetch(query, fetcher, minLen = 2, delay = 300) {
  const [results, setResults] = React.useState([]);
  const [state, setState] = React.useState("idle"); // idle | loading | ok | error | short
  const [error, setError] = React.useState(null);
  React.useEffect(() => {
    if (!query || query.length < minLen) {
      setResults([]);
      setState("short");
      return;
    }
    setState("loading");
    setError(null);
    const ctrl = new AbortController();
    const t = setTimeout(async () => {
      try {
        const data = await fetcher(query, ctrl.signal);
        setResults(data || []);
        setState("ok");
      } catch (e) {
        if (e.name === "AbortError") return;
        setError(String(e?.message || e));
        setState("error");
      }
    }, delay);
    return () => { clearTimeout(t); ctrl.abort(); };
  }, [query]);
  return { results, state, error };
}

function CustomerSearchPicker({ initial = "", onPick }) {
  const [q, setQ] = React.useState(initial);
  const fetcher = React.useCallback(async (kw, signal) => {
    const url = `${window.HS_PORTAL_BRIDGE_URL}/bridge/customers?q=${encodeURIComponent(kw)}&limit=10`;
    const res = await fetch(url, { signal, headers: { Accept: "application/json" } });
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    const data = await res.json();
    return data.customers || [];
  }, []);
  const { results, state, error } = _useDebouncedFetch(q, fetcher);

  return (
    <div className="col gap-8">
      <Field label="顧客名" required>
        <input
          type="text"
          value={q}
          onChange={(e) => setQ(e.target.value)}
          placeholder="2文字以上で GATCH マスタ検索"
          autoFocus
        />
      </Field>
      <div className="tiny" style={{ marginTop: 4 }}>
        GATCH 顧客マスタからのサジェスト
        {state === "loading" && " · 検索中…"}
        {state === "ok" && ` · ${results.length}件`}
        {state === "short" && " · (2文字以上で検索)"}
        {state === "error" && ` · 接続失敗`}
      </div>
      {state === "error" && (
        <div className="tiny" style={{ color: "var(--danger, #c00)", padding: "4px 8px" }}>
          {error} — bridge API URL: {window.HS_PORTAL_BRIDGE_URL}
        </div>
      )}
      {results.map((c) => (
        <button
          key={c.customer_gatch_id}
          className="list-row"
          onClick={() => onPick(c.customer_name)}
          style={{ borderRadius: 10, border: "1px solid var(--border)" }}
        >
          <div className="grow">
            <div className="title">{c.customer_name}</div>
            <div className="meta">
              <span className="mono">#{c.customer_gatch_id}</span>
              {c.phone && ` · ${c.phone}`}
              {c.address && ` · ${c.address.slice(0, 24)}${c.address.length > 24 ? "…" : ""}`}
            </div>
          </div>
          <Ico.arrowR style={{ color: "var(--text-4)" }} />
        </button>
      ))}
      <button
        className="list-row"
        onClick={() => onPick(q)}
        style={{ borderRadius: 10, border: "1px dashed var(--border)", marginTop: 4 }}
        disabled={!q}
      >
        <div className="grow">
          <div className="title">この名前のまま使う: 「{q || "(未入力)"}」</div>
          <div className="meta">GATCH 未登録の顧客として受付</div>
        </div>
      </button>
    </div>
  );
}

function VehicleSearchPicker({ initialPlate = "", initialModel = "", customerName = "", mode = "model", onPick }) {
  // mode = "model" → 車種で検索 (plate も併記)
  // mode = "plate" → 登録番号で検索
  const [q, setQ] = React.useState(mode === "plate" ? initialPlate : initialModel);
  const fetcher = React.useCallback(async (kw, signal) => {
    const params = new URLSearchParams();
    if (mode === "plate") params.set("plate", kw);
    else {
      // 車種検索は plate 末尾4桁 LIKE 検索を兼ねる: bridge_master_api 側で柔軟対応
      // 数字なら plate、それ以外なら customer_name で絞る
      if (/^\d+$/.test(kw)) params.set("plate", kw);
      else if (customerName) {
        params.set("customer_name", customerName);
        params.set("plate", kw); // 部分一致
      } else {
        params.set("plate", kw);
      }
    }
    if (customerName) params.set("customer_name", customerName);
    const url = `${window.HS_PORTAL_BRIDGE_URL}/bridge/vehicles?${params}`;
    const res = await fetch(url, { signal, headers: { Accept: "application/json" } });
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    const data = await res.json();
    return data.vehicles || [];
  }, [mode, customerName]);
  const { results, state, error } = _useDebouncedFetch(q, fetcher, 2, 350);

  return (
    <div className="col gap-8">
      <Field label={mode === "plate" ? "登録番号" : "車種・車名"} required>
        <input
          type="text"
          value={q}
          onChange={(e) => setQ(e.target.value)}
          placeholder={mode === "plate" ? "例: 京都 100 あ 4491 (末尾4桁でも可)" : "例: VOXY / エルフ"}
          autoFocus
        />
      </Field>
      <div className="tiny" style={{ marginTop: 4 }}>
        GATCH 車両マスタからのサジェスト
        {state === "loading" && " · 検索中…"}
        {state === "ok" && ` · ${results.length}件`}
        {state === "short" && " · (2文字以上で検索)"}
        {state === "error" && ` · 接続失敗`}
        {customerName && ` · 顧客「${customerName}」で絞り込み`}
      </div>
      {state === "error" && (
        <div className="tiny" style={{ color: "var(--danger, #c00)", padding: "4px 8px" }}>
          {error}
        </div>
      )}
      {results.map((v) => {
        const model = v["車名単独"] || v["車両全名称"] || "";
        const plate = v["登録番号"] || "";
        const chassis = v["車台番号"] || "";
        const owner = v["取引先名"] || "";
        return (
          <button
            key={`${v["車両番号"]}-${plate}`}
            className="list-row"
            onClick={() => onPick({ model, plate })}
            style={{ borderRadius: 10, border: "1px solid var(--border)" }}
          >
            <div className="grow">
              <div className="title">{model || "(車名未登録)"} {plate && <span className="mono" style={{ fontSize: 12, marginLeft: 6 }}>{plate}</span>}</div>
              <div className="meta">
                {chassis && <span className="mono">{chassis}</span>}
                {owner && ` · ${owner}`}
              </div>
            </div>
            <Ico.arrowR style={{ color: "var(--text-4)" }} />
          </button>
        );
      })}
      <button
        className="list-row"
        onClick={() => onPick(mode === "plate" ? { plate: q } : { model: q })}
        style={{ borderRadius: 10, border: "1px dashed var(--border)", marginTop: 4 }}
        disabled={!q}
      >
        <div className="grow">
          <div className="title">この{mode === "plate" ? "登録番号" : "車種"}のまま使う: 「{q || "(未入力)"}」</div>
          <div className="meta">GATCH 未登録車両として受付</div>
        </div>
      </button>
    </div>
  );
}

Object.assign(window, {
  HomeScreen, IntakeScreen, CompleteScreen, CaseDetailScreen, CaseListScreen,
  CustomerSearchPicker, VehicleSearchPicker,
});

// ─────────── Helper components ───────────
function StructuringDots() {
  return (
    <span className="text-xs muted" style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
      <span style={{ display: "inline-flex", gap: 2 }}>
        <span style={{ width: 4, height: 4, borderRadius: 99, background: "var(--primary)", animation: "bounce 0.9s ease-in-out infinite" }} />
        <span style={{ width: 4, height: 4, borderRadius: 99, background: "var(--primary)", animation: "bounce 0.9s ease-in-out infinite 0.15s" }} />
        <span style={{ width: 4, height: 4, borderRadius: 99, background: "var(--primary)", animation: "bounce 0.9s ease-in-out infinite 0.3s" }} />
      </span>
      解析中
    </span>
  );
}

function StructureSummary({ fields }) {
  const filled = Object.values(fields).filter(f => f.filled).length;
  const low = Object.values(fields).filter(f => f.filled && f.confidence < 0.8).length;
  return (
    <div style={{
      display: "flex", alignItems: "center", gap: 12,
      padding: "10px 14px",
      background: "var(--success-soft)",
      border: "1px solid oklch(0.75 0.08 155)",
      borderRadius: 10,
      color: "oklch(0.32 0.10 155)",
      fontSize: 12, fontWeight: 600,
    }}>
      <Ico.checkSmall style={{ width: 18, height: 18, color: "var(--success)" }} />
      <span style={{ flex: 1 }}>
        <span className="bold">{filled}項目</span>を自動入力
        {low > 0 && (
          <span style={{ color: "oklch(0.45 0.13 60)", marginLeft: 8 }}>
            · 確認要 <span className="bold">{low}項目</span>
          </span>
        )}
      </span>
    </div>
  );
}

function NotifAnim({ done, icon, label, meta }) {
  return (
    <div className="notif" style={{ opacity: done ? 1 : 0.55, transition: "opacity 0.3s ease" }}>
      <div className="ico-wrap" style={done ? {} : { background: "var(--surface-3)", color: "var(--text-3)" }}>
        {icon === "chat" ? <Ico.chat /> : icon === "cal" ? <Ico.cal /> : icon === "list" ? <Ico.list /> : <Ico.phone />}
      </div>
      <div style={{ flex: 1 }}>
        <div className="label">{label}</div>
        <div className="meta">{done ? meta : "送信中…"}</div>
      </div>
      {done ? (
        <div className="check" style={{ animation: "pop 0.4s ease both" }}><Ico.checkSmall /></div>
      ) : (
        <div style={{
          width: 22, height: 22, borderRadius: 999,
          border: "2px solid var(--border-strong)", borderTopColor: "transparent",
          animation: "spin 0.8s linear infinite",
        }} />
      )}
    </div>
  );
}

Object.assign(window, { StructuringDots, StructureSummary, NotifAnim });

// ─────────── Purchase report components ───────────
function PurchaseBadge({ status }) {
  const s = PURCHASE_STATUS[status] || PURCHASE_STATUS.pending;
  return (
    <span className={`badge ${s.className}`}><span className="dot" />{s.label}</span>
  );
}

function PurchaseReportSheet({ open, onClose, caseRef, onShowToast }) {
  const [step, setStep] = rsState(1); // 1: form, 2: confirm, 3: done
  const [supplier, setSupplier] = rsState("");
  const [supplierSheet, setSupplierSheet] = rsState(false);
  const [category, setCategory] = rsState("部品");
  const [item, setItem] = rsState("");
  const [amount, setAmount] = rsState("");
  const [qty, setQty] = rsState(1);
  const [note, setNote] = rsState("");
  const [hasReceipt, setHasReceipt] = rsState(false);

  rsEffect(() => {
    if (open) {
      setStep(1); setSupplier(""); setCategory("部品"); setItem("");
      setAmount(""); setQty(1); setNote(""); setHasReceipt(false);
    }
  }, [open]);

  const canSubmit = supplier && item && amount;
  const total = (parseInt(amount) || 0) * qty;

  const submit = () => {
    setStep(3);
    setTimeout(() => {
      onClose();
      onShowToast && onShowToast("仕入報告を送信しました");
    }, 1100);
  };

  return (
    <>
      <div className={`scrim ${open ? "show" : ""}`} onClick={onClose} />
      <div className={`sheet ${open ? "show" : ""}`} style={{ maxHeight: "92%" }}>
        <div className="sheet-handle" />
        <div className="sheet-head">
          <div>
            <div className="sheet-title">仕入を報告</div>
            <div className="text-xs muted" style={{ marginTop: 2 }}>
              <span className="mono">{caseRef.key}</span> · {caseRef.customer}
            </div>
          </div>
          <button className="appbar icon-btn" onClick={onClose} style={{ width: 32, height: 32, padding: 0 }}>
            <Ico.x />
          </button>
        </div>

        {step === 3 ? (
          <div style={{ padding: "40px 24px", textAlign: "center" }}>
            <div style={{
              width: 56, height: 56, borderRadius: 999,
              background: "var(--success)", color: "white",
              display: "grid", placeItems: "center", margin: "0 auto 12px",
              animation: "pop 0.4s ease",
            }}><Ico.check style={{ width: 28, height: 28 }} /></div>
            <div className="bold" style={{ fontSize: 16 }}>送信しました</div>
            <div className="text-xs muted" style={{ marginTop: 4 }}>承認後、GATCHに反映されます</div>
          </div>
        ) : (
          <div className="sheet-body">
            <div className="col gap-8">
              {/* Linked case info */}
              <div style={{
                padding: "10px 12px", borderRadius: 10,
                background: "var(--primary-soft)",
                display: "flex", gap: 10, alignItems: "center",
              }}>
                <div style={{ width: 28, height: 28, borderRadius: 8, background: "var(--primary)", color: "var(--on-primary)", display: "grid", placeItems: "center" }}>
                  <Ico.car />
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div className="text-xs muted" style={{ fontSize: 10 }}>紐付け案件</div>
                  <div className="bold text-sm" style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                    {caseRef.customer} · {caseRef.model}
                  </div>
                </div>
              </div>

              {/* Supplier */}
              <Field label="仕入先" required value={supplier} onClick={() => setSupplierSheet(true)} placeholder="選択してください" />

              {/* Category */}
              <Field label="区分" required>
                <div style={{ display: "flex", gap: 6, marginTop: 8, flexWrap: "wrap" }}>
                  {PURCHASE_CATEGORIES.map(opt => (
                    <button key={opt} className={`chip ${category === opt ? "on" : ""}`}
                      onClick={() => setCategory(opt)} style={{ height: 32, fontSize: 12 }}>
                      {opt}
                    </button>
                  ))}
                </div>
              </Field>

              {/* Item */}
              <Field label="品目 / 内容" required>
                <input type="text" value={item} onChange={e => setItem(e.target.value)}
                  placeholder="例: ブレーキパッド フロント / リアセット" />
              </Field>

              {/* Amount + qty */}
              <div style={{ display: "grid", gridTemplateColumns: "2fr 1fr", gap: 8 }}>
                <Field label="単価 (税抜)" required>
                  <div className="row" style={{ alignItems: "baseline" }}>
                    <span className="muted text-sm" style={{ marginRight: 4 }}>¥</span>
                    <input type="number" value={amount} onChange={e => setAmount(e.target.value)}
                      placeholder="0" style={{ flex: 1, fontFamily: "var(--font-num)", fontVariantNumeric: "tabular-nums" }} />
                  </div>
                </Field>
                <Field label="数量" required>
                  <div className="row" style={{ alignItems: "center" }}>
                    <button onClick={() => setQty(Math.max(1, qty - 1))} style={{ width: 24, height: 24, borderRadius: 6, background: "var(--surface-3)", color: "var(--text-2)" }}>−</button>
                    <input type="number" value={qty} onChange={e => setQty(Math.max(1, parseInt(e.target.value) || 1))}
                      style={{ flex: 1, textAlign: "center", fontFamily: "var(--font-num)" }} />
                    <button onClick={() => setQty(qty + 1)} style={{ width: 24, height: 24, borderRadius: 6, background: "var(--surface-3)", color: "var(--text-2)" }}>+</button>
                  </div>
                </Field>
              </div>

              {/* Total */}
              {amount && (
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", padding: "10px 12px", background: "var(--surface-3)", borderRadius: 10 }}>
                  <span className="tiny">小計 (税抜)</span>
                  <span className="num bold" style={{ fontSize: 20 }}>¥{total.toLocaleString()}</span>
                </div>
              )}

              {/* Receipt upload */}
              <Field label="伝票・領収書">
                <button onClick={() => setHasReceipt(!hasReceipt)}
                  style={{
                    marginTop: 6, display: "flex", alignItems: "center", gap: 10, padding: "10px 12px",
                    border: `1px dashed ${hasReceipt ? "var(--success)" : "var(--border-strong)"}`,
                    borderRadius: 10, background: hasReceipt ? "var(--success-soft)" : "var(--surface-2)",
                    color: hasReceipt ? "oklch(0.36 0.12 155)" : "var(--text-2)",
                    width: "100%", textAlign: "left",
                  }}>
                  {hasReceipt ? <Ico.check style={{ width: 18, height: 18 }} /> : <Ico.plus />}
                  <span className="text-sm bold">{hasReceipt ? "伝票画像を添付しました (1枚)" : "写真を撮影 / 画像を選択"}</span>
                </button>
              </Field>

              {/* Note */}
              <Field label="備考">
                <textarea value={note} onChange={e => setNote(e.target.value)}
                  rows={2} placeholder="メーカー / 型番 / 急ぎフラグなど" />
              </Field>

              {/* CTA */}
              <button className="btn primary lg block"
                disabled={!canSubmit}
                style={{ opacity: canSubmit ? 1 : 0.5, marginTop: 4 }}
                onClick={submit}>
                <Ico.check /> 仕入報告を送信
              </button>
              <div className="text-xs muted" style={{ textAlign: "center" }}>
                送信後、整備セクション管理者の承認を経てGATCHに反映されます
              </div>
            </div>
          </div>
        )}
      </div>

      {/* Supplier picker (nested sheet) */}
      <Sheet open={supplierSheet} onClose={() => setSupplierSheet(false)} title="仕入先を選択">
        <div className="col gap-4">
          {SUPPLIERS.map(s => (
            <button key={s} className="list-row"
              onClick={() => { setSupplier(s); setSupplierSheet(false); }}
              style={{ borderRadius: 10, border: "1px solid var(--border)" }}>
              <div className="grow"><div className="title">{s}</div></div>
              {supplier === s && <Ico.check style={{ color: "var(--primary)" }} />}
            </button>
          ))}
        </div>
      </Sheet>
    </>
  );
}

function PurchaseDetailSheet({ purchase, onClose }) {
  if (!purchase) return null;
  const total = purchase.amount * purchase.qty;
  return (
    <>
      <div className="scrim show" onClick={onClose} />
      <div className="sheet show" style={{ maxHeight: "85%" }}>
        <div className="sheet-handle" />
        <div className="sheet-head">
          <div>
            <div className="sheet-title">仕入詳細</div>
            <div className="text-xs muted mono" style={{ marginTop: 2 }}>{purchase.id}</div>
          </div>
          <button className="appbar icon-btn" onClick={onClose} style={{ width: 32, height: 32 }}>
            <Ico.x />
          </button>
        </div>
        <div className="sheet-body">
          <div style={{ padding: 14, borderRadius: 12, background: "var(--surface-3)", marginBottom: 12 }}>
            <PurchaseBadge status={purchase.status} />
            <div className="bold" style={{ fontSize: 18, marginTop: 8 }}>{purchase.item}</div>
            <div className="text-sm muted" style={{ marginTop: 2 }}>{purchase.supplier} · {purchase.category}</div>
          </div>
          <div className="card" style={{ padding: 0 }}>
            <DetailRow label="単価 (税抜)" value={`¥${purchase.amount.toLocaleString()}`} />
            <DetailRow label="数量" value={`${purchase.qty}`} />
            <DetailRow label="小計" value={`¥${total.toLocaleString()}`} />
            <DetailRow label="報告者" value={purchase.reportedBy} />
            <DetailRow label="報告日時" value={purchase.reportedAt} />
            <DetailRow label="伝票" value={purchase.hasReceipt ? "添付あり 📎" : "未添付"} />
            <DetailRow label="備考" value={purchase.note || "—"} last />
          </div>
          {purchase.status === "pending" && (
            <div className="row gap-8" style={{ marginTop: 14 }}>
              <button className="btn" style={{ flex: 1 }}>編集</button>
              <button className="btn primary" style={{ flex: 1 }}>承認依頼</button>
            </div>
          )}
        </div>
      </div>
    </>
  );
}

Object.assign(window, { PurchaseBadge, PurchaseReportSheet, PurchaseDetailSheet });
