// view-partner.jsx — Portail Partenaire (/p/:token)
function greetingFor(partner, t) {
  if (t && t.localGreeting === false) return "Hello";
  return GREETINGS[partner.cc] || "Hello";
}
function firstName(partner) {
  const n = partner.company.split(/[\s,]+/)[0];
  return n.charAt(0) + n.slice(1).toLowerCase();
}

function ValidationScope({ validation }) {
  const parts = validation === "MPC + Vidéo" ? ["the MPC sample", "the production video"]
    : validation === "Vidéo" ? ["the production video"] : ["the MPC sample"];
  const joiner = validation === "MPC + Vidéo" ? " or " : " and ";
  return <span>{parts.map((p, i) => <strong key={p}>{p}{i < parts.length - 1 ? <span style={{ fontWeight: 400 }}>{joiner}</span> : null}</strong>)}</span>;
}

function ApproveModal({ prod, partner, onClose, onConfirm }) {
  const [name, setName] = React.useState("");
  const both = prod.validation === "MPC + Vidéo";
  const videoAvail = !!prod.mpcVideoUrl;
  const [via, setVia] = React.useState(both ? (videoAvail ? "MPC + Vidéo" : "MPC") : (prod.validation || "MPC"));
  const viaBtn = ([v, lbl, off]) => (
    <button key={v} disabled={off} onClick={() => setVia(v)} title={off ? "The video link isn't available yet" : ""}
      style={{ border: "none", padding: "5px 13px", fontSize: 12, fontWeight: 700, cursor: off ? "not-allowed" : "pointer", fontFamily: K.font, whiteSpace: "nowrap",
        background: via === v ? K.black : "transparent", color: via === v ? "#FFF" : off ? "#CBC7C0" : K.sub }}>{lbl}</button>
  );
  return (
    <Modal title="Approve for mass production" onClose={onClose}>
      <p style={{ margin: "0 0 6px" }}>You are approving <ValidationScope validation={via} /> for <strong>{prod.gameLabel}</strong> ({prod.qty.toLocaleString("fr-FR")} units).</p>
      {both && (
        <div style={{ margin: "12px 0 4px" }}>
          <div className="k-label" style={{ marginBottom: 6 }}>You are approving based on…</div>
          <div style={{ display: "inline-flex", border: `1.5px solid ${K.line}`, borderRadius: 99, overflow: "hidden" }}>
            {[["MPC", "The MPC sample", false], ["Vidéo", "The video", !videoAvail], ["MPC + Vidéo", "Both", !videoAvail]].map(viaBtn)}
          </div>
          <div style={{ fontSize: 11.5, color: K.sub, marginTop: 5 }}>
            {videoAvail
              ? "One approval is enough — it covers the whole production, whichever you reviewed."
              : "The video link isn't available yet — you can approve on the MPC sample alone, no need to wait."}
          </div>
        </div>
      )}
      <Banner tone="amber" style={{ margin: "12px 0" }}>
        This approval is binding and authorizes KODAMA and the factory to launch mass production.
      </Banner>
      <div className="k-label" style={{ marginBottom: 6 }}>Your full name (signature)</div>
      <input className="k-input" autoFocus placeholder="e.g. Laura Bianchi" value={name} onChange={(e) => setName(e.target.value)} />
      <div style={{ display: "flex", gap: 10, marginTop: 18, justifyContent: "flex-end" }}>
        <button className="k-btn k-btn-ghost" onClick={onClose}>Cancel</button>
        <button className="k-btn k-btn-primary" disabled={name.trim().length < 3} onClick={() => onConfirm(name.trim(), via)}>✓&nbsp; Approve &amp; launch production</button>
      </div>
    </Modal>
  );
}

function ChangesModal({ prod, onClose, onConfirm }) {
  const [text, setText] = React.useState("");
  return (
    <Modal title="Request changes" onClose={onClose}>
      <p style={{ margin: "0 0 10px" }}>Tell us what needs to change on <strong>{prod.gameLabel}</strong>. Production stays on hold until the files are updated.</p>
      <textarea className="k-textarea" rows={4} autoFocus placeholder="Describe the issue — component, page, language…" value={text} onChange={(e) => setText(e.target.value)} style={{ fontFamily: K.font, fontSize: 14 }}></textarea>
      <div style={{ display: "flex", gap: 10, marginTop: 16, justifyContent: "flex-end" }}>
        <button className="k-btn k-btn-ghost" onClick={onClose}>Cancel</button>
        <button className="k-btn k-btn-primary" disabled={text.trim().length < 5} onClick={() => onConfirm(text.trim())}>Send to KODAMA</button>
      </div>
    </Modal>
  );
}

function valLabel(validation) {
  if (!validation) return "Not chosen yet";
  return validation === "MPC + Vidéo" ? "MPC sample + video" : validation === "Vidéo" ? "Production video" : "MPC sample";
}

function ValidationPref({ prod, partner, update, push }) {
  if (prod.mpcOk) return <div style={{ fontSize: 13.5, fontWeight: 600 }}>{valLabel(prod.validation)}</div>;
  const unset = !prod.validation;
  const set = (v) => {
    if (v === prod.validation) return;
    update((db) => {
      const p = db.productions.find((x) => x.id === prod.id);
      p.validation = v;
      db.log.unshift({ ts: nowStamp(), actor: partner.company, action: "Validation method chosen", detail: `${prod.gameLabel} — ${valLabel(v)}` });
    });
    push("Validation method saved — " + valLabel(v) + ".");
  };
  const btn = ([v, lbl]) => (
    <button key={v} onClick={() => set(v)}
      style={{ border: "none", padding: "4px 10px", fontSize: 11.5, fontWeight: 700, cursor: "pointer", fontFamily: K.font, whiteSpace: "nowrap",
        background: prod.validation === v ? K.black : "transparent", color: prod.validation === v ? "#FFF" : K.sub }}>{lbl}</button>
  );
  return (
    <div>
      <div style={{ display: "inline-flex", border: `1.5px solid ${unset ? K.amber : K.line}`, borderRadius: 99, overflow: "hidden" }}>
        {[["MPC", "MPC"], ["MPC + Vidéo", "MPC + video"], ["Vidéo", "Video"]].map(btn)}
      </div>
      {unset && <div style={{ fontSize: 11, color: K.amber, marginTop: 3, fontWeight: 700 }}>⚠ Please choose</div>}
    </div>
  );
}

function BasicDataModal({ prod, onClose }) {
  const [tab, setTab] = React.useState("production");
  const basic = prod.basic;
  const groups = [...new Set(BASIC_FIELDS.filter((f) => f.group !== "Identification").map((f) => f.group))];
  const tabBtn = (k, lbl) => (
    <button key={k} onClick={() => setTab(k)} style={{ border: "none", padding: "5px 14px", fontSize: 12, fontWeight: 700, cursor: "pointer", fontFamily: K.font, background: tab === k ? K.black : "transparent", color: tab === k ? "#FFF" : K.sub }}>{lbl}</button>
  );
  const prodRows = [
    ["Quantity ordered", prod.qty.toLocaleString("fr-FR") + " units"],
    ["Cartons", prod.pallets ? "≈ " + prod.pallets.cartons.toLocaleString("fr-FR") : "—"],
    ["Pallets", prod.wantsPallets === false ? "None — floor-loaded" : prod.pallets && prod.pallets.pallets ? "≈ " + prod.pallets.pallets : "—"],
    ["Pallet cost", prod.wantsPallets === false ? "n/a — floor-loaded" : prod.pallets && prod.pallets.cost ? "$ " + prod.pallets.cost.toLocaleString("en-US") + " (" + Math.ceil(prod.pallets.pallets) + " × $" + PALLET_COST_USD + ")" : "—"],
    ["Units per carton", basic && basic.unitsPerCarton ? basic.unitsPerCarton : "—"],
    ["Carton weight (full)", basic && basic.cartonFull ? basic.cartonFull + " kg" : "—"],
    ["Est. total weight", basic && basic.gameWeight ? "≈ " + Math.round(prod.qty * basic.gameWeight).toLocaleString("fr-FR") + " kg" : "—"],
  ];
  return (
    <Modal title={`Logistics data — ${prod.game}`} onClose={onClose}>
      <p style={{ margin: "0 0 10px", fontSize: 12.5, color: K.sub }}>Read-only — maintained by the factory. {prod.game} · {prod.printLabel}.</p>
      <div style={{ display: "inline-flex", border: `1.5px solid ${K.line}`, borderRadius: 99, overflow: "hidden", marginBottom: 4 }}>
        {tabBtn("production", "Your production")}{tabBtn("game", "Game & cartons")}
      </div>
      {tab === "production" && (
        !basic ? (
          <Banner tone="amber" style={{ marginTop: 10 }}>The factory hasn't filled in the logistics data for {prod.game} yet — quantities will appear here as soon as it's available.</Banner>
        ) : (
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(170px, 1fr))", gap: "12px 22px", marginTop: 10 }}>
            {prodRows.map(([k, v]) => (
              <div key={k}>
                <div style={{ fontSize: 11, color: K.sub }}>{k}</div>
                <div style={{ fontSize: 13.5, fontWeight: 600 }}>{v}</div>
              </div>
            ))}
          </div>
        )
      )}
      {tab === "game" && (
        !basic ? (
          <Banner tone="amber" style={{ marginTop: 10 }}>The factory hasn't filled in the logistics data for {prod.game} yet — it will appear here as soon as it's available.</Banner>
        ) : (
          <div style={{ maxHeight: "55vh", overflowY: "auto", marginTop: 2 }}>
            {groups.map((g) => (
              <div key={g}>
                <div className="k-label" style={{ margin: "14px 0 6px" }}>{g}</div>
                <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(170px, 1fr))", gap: "10px 22px" }}>
                  {BASIC_FIELDS.filter((f) => f.group === g).map((f) => (
                    <div key={f.key}>
                      <div style={{ fontSize: 11, color: K.sub }}>{f.label}{f.unit ? ` (${f.unit})` : ""}</div>
                      <div style={{ fontSize: 13, fontWeight: 600, fontFamily: f.type === "text" ? K.mono : K.font, color: basic[f.key] == null || basic[f.key] === "" ? K.sub : K.ink }}>
                        {basic[f.key] == null || basic[f.key] === "" ? "—" : String(basic[f.key])}
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            ))}
          </div>
        )
      )}
      <div style={{ display: "flex", justifyContent: "flex-end", marginTop: 16 }}>
        <button className="k-btn k-btn-ghost" onClick={onClose}>Close</button>
      </div>
    </Modal>
  );
}

function PalletPref({ prod, partner, update, push }) {
  const unset = prod.wantsPallets == null;
  const set = (v) => {
    if (v === prod.wantsPallets) return;
    update((db) => {
      const p = db.productions.find((x) => x.id === prod.id);
      p.wantsPallets = v;
      db.log.unshift({ ts: nowStamp(), actor: partner.company, action: "Pallet preference updated", detail: `${prod.gameLabel} — ${v ? "on pallets" : "loose cartons"}` });
    });
    push(v ? "Noted — your order will ship on pallets." : "Noted — your order will ship as loose cartons.");
  };
  const btn = (v, lbl) => (
    <button key={lbl} onClick={() => set(v)}
      style={{ border: "none", padding: "4px 12px", fontSize: 11.5, fontWeight: 700, cursor: "pointer", fontFamily: K.font,
        background: prod.wantsPallets === v ? K.black : "transparent", color: prod.wantsPallets === v ? "#FFF" : K.sub }}>{lbl}</button>
  );
  return (
    <div>
      <div style={{ display: "inline-flex", border: `1.5px solid ${unset ? K.amber : K.line}`, borderRadius: 99, overflow: "hidden" }}>
        {btn(true, "Yes")}{btn(false, "No")}
      </div>
      <div style={{ fontSize: 11, color: unset ? K.amber : K.sub, marginTop: 3, fontWeight: unset ? 700 : 400 }}>
        {unset ? "⚠ Please choose" : prod.wantsPallets
          ? <span>{prod.pallets && prod.pallets.pallets ? `≈ ${prod.pallets.pallets} pallets` : "Shipped on pallets"}{prod.pallets && prod.pallets.cost ? <span> · pallet cost <strong style={{ color: K.ink }}>$ {prod.pallets.cost.toLocaleString("en-US")}</strong></span> : null}</span>
          : "Loose cartons (floor-loaded)"}
      </div>
    </div>
  );
}

function IncotermPref({ prod, partner, update, push }) {
  const unset = !prod.incoterm;
  const set = (v) => {
    if (v === prod.incoterm) return;
    update((db) => {
      const p = db.productions.find((x) => x.id === prod.id);
      p.incoterm = v;
      db.log.unshift({ ts: nowStamp(), actor: partner.company, action: "Packing list incoterm chosen", detail: `${prod.gameLabel} — ${v} (${v === "FOB" ? "Free On Board" : "Ex Works"})` });
    });
    push(v === "FOB" ? "Noted — your packing list will be issued FOB (Free On Board)." : "Noted — your packing list will be issued EXW (Ex Works).");
  };
  const btn = (v) => (
    <button key={v} onClick={() => set(v)}
      style={{ border: "none", padding: "4px 12px", fontSize: 11.5, fontWeight: 700, cursor: "pointer", fontFamily: K.font,
        background: prod.incoterm === v ? K.black : "transparent", color: prod.incoterm === v ? "#FFF" : K.sub }}>{v}</button>
  );
  return (
    <div>
      <div style={{ display: "inline-flex", border: `1.5px solid ${unset ? K.amber : K.line}`, borderRadius: 99, overflow: "hidden" }}>
        {btn("FOB")}{btn("EXW")}
      </div>
      <div style={{ fontSize: 11, color: unset ? K.amber : K.sub, marginTop: 3, fontWeight: unset ? 700 : 400 }}>
        {unset ? "⚠ Please choose" : prod.incoterm === "FOB" ? "Free On Board" : "Ex Works"}
      </div>
    </div>
  );
}

// ——— Récap « à remplir » en tête de page : tout ce que le partenaire n'a pas encore renseigné ———
function todoScrollTo(sel) {
  const el = document.querySelector(sel);
  if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 76, behavior: "smooth" });
}

function buildTodoItems(prods, partner) {
  const items = [];
  prods.forEach((p) => {
    const where = `${p.game} · ${p.printLabel}`;
    const anchor = `[data-comment-anchor="prod-${p.id}"]`;
    if (!p.validation) items.push({ k: p.id + "-val", anchor, where, text: <span>Choose your <strong>pre-prod validation method</strong> (MPC / video)</span> });
    if (p.wantsPallets == null) items.push({ k: p.id + "-pal", anchor, where, text: <span>Tell us if you want <strong>delivery on pallets</strong></span> });
    if (!p.incoterm) items.push({ k: p.id + "-inc", anchor, where, text: <span>Choose your packing list <strong>incoterm</strong> — FOB or EXW</span> });
    if (p.validation && needsApproval(p)) items.push({ k: p.id + "-mpc", anchor, where, text: <span>Review &amp; <strong>approve the MPC</strong> to launch mass production</span> });
  });
  const consigneeEmpty = !partner.consignee || !partner.consignee.trim();
  const preprodEmpty = !partner.preprod || !partner.preprod.trim();
  if (consigneeEmpty) items.push({ k: "consignee", anchor: '[data-todo-anchor="consignee"]', where: "shipping information", text: <span>Fill in your <strong>Consignee &amp; Notify Party</strong></span> });
  if (preprodEmpty) items.push({ k: "preprod", anchor: '[data-todo-anchor="preprod"]', where: "shipping information", text: <span>Fill in your <strong>pre-production samples address</strong></span> });
  if (!consigneeEmpty && !preprodEmpty && monthsAgo(partner.confirmedOn) > 6) {
    items.push({ k: "confirm", anchor: '[data-todo-anchor="consignee"]', where: "shipping information", text: <span><strong>Confirm your shipping information</strong> is still accurate{partner.confirmedOn ? ` — last confirmed ${fmtDate(partner.confirmedOn)}` : ""}</span> });
  }
  return items;
}

function TodoRecap({ prods, partner }) {
  const items = buildTodoItems(prods, partner);
  if (items.length === 0) return null;
  return (
    <div className="k-card" style={{ marginTop: 20, overflow: "hidden" }} data-comment-anchor="partner-todo-recap">
      <div style={{ padding: "11px 22px", background: K.amberBg, display: "flex", alignItems: "center", gap: 10 }}>
        <span style={{ fontSize: 16 }}>📋</span>
        <span className="k-round" style={{ fontSize: 16, fontWeight: 700, color: K.amber }}>Still needed from you</span>
        <Pill fg={K.amber} bg="#FFF">{items.length}</Pill>
        <span style={{ marginLeft: "auto", fontSize: 11.5, color: K.amber, fontWeight: 600 }}>click an item to jump to it</span>
      </div>
      <div>
        {items.map((it, i) => (
          <button key={it.k} onClick={() => todoScrollTo(it.anchor)} style={{ display: "flex", width: "100%", textAlign: "left", alignItems: "baseline", gap: 10, background: "none", border: "none", borderTop: i === 0 ? "none" : `1px solid ${K.line}`, padding: "10px 22px", cursor: "pointer", fontFamily: K.font, fontSize: 13.5, color: K.ink }}>
            <span style={{ color: K.amber, fontWeight: 800, flexShrink: 0 }}>→</span>
            <span style={{ flex: 1 }}>{it.text}</span>
            <span style={{ color: K.sub, fontSize: 12, whiteSpace: "nowrap", fontWeight: 600 }}>{it.where}</span>
          </button>
        ))}
      </div>
    </div>
  );
}

function ProdCard({ prod, partner, update, push }) {
  const [modal, setModal] = React.useState(null); // 'approve' | 'changes' | 'basic'
  const gc = gameColor(prod.game);
  const [justApproved, setJustApproved] = React.useState(false);
  const st = STATUS[prod.statut] || { en: prod.statut, fg: K.gray, bg: K.grayBg };
  const needsAction = needsApproval(prod);
  const wantsVideo = !!prod.validation && prod.validation.includes("Vidéo");
  const wantsMpc = !prod.validation || prod.validation.includes("MPC");
  const videoMissing = wantsVideo && !prod.mpcVideoUrl;
  const canApprove = !!prod.validation && !(prod.validation === "Vidéo" && videoMissing);

  const approve = (name, via) => {
    update((db) => {
      const p = db.productions.find((x) => x.id === prod.id);
      p.mpcOk = true; p.mpcBy = name; p.mpcOn = todayIso(); p.mpcVia = via || prod.validation || "MPC"; p.statut = "MPC validé";
      db.log.unshift({ ts: nowStamp(), actor: `${name} (${partner.company.split(" ")[0]})`, action: "MPC approved", detail: `${prod.gameLabel} — ${valLabel(via || prod.validation)}` });
    });
    setModal(null); setJustApproved(true);
    push("Approval recorded — thank you! The factory has been notified.");
  };
  const requestChanges = (text) => {
    update((db) => {
      const p = db.productions.find((x) => x.id === prod.id);
      p.comment = text; p.statut = "Modifications des fichiers";
      db.log.unshift({ ts: nowStamp(), actor: partner.company, action: "Changes requested", detail: `${prod.gameLabel} — ${text.slice(0, 60)}` });
    });
    setModal(null);
    push("Change request sent to KODAMA.");
  };

  return (
    <div className="k-card" style={{ marginTop: 14, overflow: "hidden" }} data-comment-anchor={"prod-" + prod.id}>
      <div style={{ height: 4, background: needsAction ? K.grad : `linear-gradient(90deg, ${gc.mid}, ${gc.soft})` }}></div>
      <div style={{ padding: "18px 22px 14px", display: "flex", justifyContent: "space-between", gap: 12, flexWrap: "wrap" }}>
        <div>
          <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
            <span className="k-round" style={{ fontSize: 25, fontWeight: 700, lineHeight: 1.15 }}>{prod.game}</span>
            <Pill fg={gc.fg} bg={gc.soft}>{prod.printLabel}</Pill>
            <span style={{ color: K.sub, fontWeight: 600, fontSize: 13.5 }}>{prod.qty.toLocaleString("fr-FR")} units</span>
          </div>
          <div style={{ color: K.sub, fontSize: 13, marginTop: 3 }}>{fmtDate(prod.prodStart)} → {fmtDate(prod.prodEnd)}</div>
        </div>
        <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 8 }}>
          <Pill fg={st.fg} bg={st.bg}>{st.dot ? st.dot + " " : ""}{st.en}</Pill>
          <button className="k-btn k-btn-primary k-btn-sm" onClick={() => setModal("basic")}>Logistics data</button>
        </div>
      </div>
      <div style={{ margin: "0 22px 12px", borderRadius: 12, padding: "12px 16px", background: "#FAF9F7", border: `1.5px solid ${K.line}`, display: "flex", gap: 26, flexWrap: "wrap" }}>
        <div>
          <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: ".06em", textTransform: "uppercase", color: K.sub }}>Pre-prod validation</div>
          <div style={{ marginTop: 3 }}><ValidationPref prod={prod} partner={partner} update={update} push={push} /></div>
        </div>
        <div>
          <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: ".06em", textTransform: "uppercase", color: K.sub }}>Delivery on pallets?</div>
          <div style={{ marginTop: 3 }}><PalletPref prod={prod} partner={partner} update={update} push={push} /></div>
        </div>
        <div>
          <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: ".06em", textTransform: "uppercase", color: K.sub }}>Packing list</div>
          <div style={{ marginTop: 3 }}><IncotermPref prod={prod} partner={partner} update={update} push={push} /></div>
        </div>
      </div>
      {(wantsMpc || prod.mpcTracking) && (
      <div style={{ margin: `0 22px ${wantsVideo ? 10 : 16}px`, borderRadius: 12, padding: "12px 16px", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, flexWrap: "wrap", background: prod.mpcTracking ? K.tealBg : "#FAF9F7", border: prod.mpcTracking ? "1.5px solid #B9DCDA" : `1.5px dashed ${K.line}` }}>
        <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
          <span style={{ fontSize: 20 }}>📦</span>
          <div>
            <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: ".06em", textTransform: "uppercase", color: prod.mpcTracking ? K.teal : K.sub }}>MPC sample tracking</div>
            {prod.mpcTracking ? (
              <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap", marginTop: 2 }}>
                <span style={{ fontFamily: K.mono, fontSize: 15.5, fontWeight: 600 }}>{prod.mpcTracking}</span>
                <CopyBtn text={prod.mpcTracking} />
              </div>
            ) : (
              <div style={{ fontSize: 13, color: K.sub, marginTop: 2 }}>No tracking number yet — it will appear here as soon as the factory ships your sample.</div>
            )}
          </div>
        </div>
        {prod.mpcTracking ? (
          <div style={{ textAlign: "right" }}>
            <div style={{ fontSize: 12.5, color: K.teal, fontWeight: 700 }}>✓ Sample shipped</div>
            {prod.mpcTrackingOn ? <div style={{ fontSize: 12, color: K.sub }}>tracking added by the factory on {fmtDate(prod.mpcTrackingOn)}</div> : null}
          </div>
        ) : (
          <Pill fg={K.gray} bg={K.grayBg}>⏳ Awaiting shipment</Pill>
        )}
      </div>
      )}

      {wantsVideo && (
      <div style={{ margin: "0 22px 16px", borderRadius: 12, padding: "12px 16px", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, flexWrap: "wrap", background: prod.mpcVideoUrl ? K.blueBg : "#FAF9F7", border: prod.mpcVideoUrl ? "1.5px solid #BFD7EE" : `1.5px dashed ${K.line}` }}>
        <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
          <span style={{ fontSize: 20 }}>🎬</span>
          <div>
            <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: ".06em", textTransform: "uppercase", color: prod.mpcVideoUrl ? K.blueS : K.sub }}>Production video</div>
            {prod.mpcVideoUrl ? (
              <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap", marginTop: 2 }}>
                <ExtLink href={prod.mpcVideoUrl} style={{ fontSize: 14.5 }}>▶ Watch the production video</ExtLink>
                <CopyBtn text={prod.mpcVideoUrl} label="Copy link" />
              </div>
            ) : (
              <div style={{ fontSize: 13, color: K.sub, marginTop: 2 }}>No video yet — KODAMA will add the link here as soon as the factory shares the footage.</div>
            )}
          </div>
        </div>
        {prod.mpcVideoUrl ? (
          <div style={{ fontSize: 12.5, color: K.blueS, fontWeight: 700 }}>✓ Video available</div>
        ) : (
          <Pill fg={K.gray} bg={K.grayBg}>⏳ Awaiting video</Pill>
        )}
      </div>
      )}

      {needsAction && (
        <div style={{ borderTop: `1px solid ${K.line}`, padding: "16px 22px" }}>
          {!prod.validation
            ? <Banner tone="amber" style={{ marginBottom: 14 }}>First, choose your <strong>pre-prod validation method</strong> above — then you'll be able to approve.</Banner>
            : <p style={{ margin: "0 0 14px" }}>Please review and approve <ValidationScope validation={prod.validation} /> so mass production can start.</p>}
          {prod.validation === "MPC + Vidéo" && (
            <p style={{ margin: "-8px 0 14px", fontSize: 12.5, color: K.sub }}>You can approve based on the MPC sample, the video, or both — a single approval launches production.</p>
          )}
          {prod.validation === "Vidéo" && videoMissing && (
            <Banner tone="amber" style={{ margin: "-4px 0 14px" }}>The production video isn't available yet — you'll be able to approve as soon as KODAMA adds the link above.</Banner>
          )}
          <div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
            <button className="k-btn k-btn-primary" disabled={!canApprove} onClick={() => setModal("approve")}>✓&nbsp; I approve</button>
            <button className="k-btn k-btn-ghost" onClick={() => setModal("changes")}>Request changes</button>
          </div>
        </div>
      )}

      {!prod.mpcOk && prod.statut !== "Modifications des fichiers" && prod.fixedOn && prod.prevComment && (
        <div style={{ borderTop: `1.5px solid ${K.green}40`, padding: "14px 22px", background: K.greenBg }}>
          <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: ".06em", textTransform: "uppercase", color: K.green }}>✓ Your requested changes have been made — {fmtDate(prod.fixedOn)}</div>
          <p style={{ margin: "6px 0 0", fontSize: 12.5, color: K.sub, whiteSpace: "pre-wrap" }}>You asked: “{prod.prevComment}”</p>
          {prod.fixNote ? <p style={{ margin: "4px 0 0", fontWeight: 600, color: K.ink, whiteSpace: "pre-wrap" }}>KODAMA: “{prod.fixNote}”</p> : null}
          <p style={{ margin: "6px 0 0", fontSize: 12.5, color: K.sub }}>Please review the updated files and approve again below.</p>
        </div>
      )}

      {prod.statut === "Modifications des fichiers" && prod.comment && (
        <div style={{ borderTop: `1.5px solid ${K.red}40`, padding: "14px 22px", background: K.redBg }}>
          <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: ".06em", textTransform: "uppercase", color: K.red }}>✎ Your change request — production on hold</div>
          <p style={{ margin: "6px 0 0", fontWeight: 600, color: K.ink, whiteSpace: "pre-wrap" }}>“{prod.comment}”</p>
          <p style={{ margin: "6px 0 0", fontSize: 12.5, color: K.sub }}>KODAMA is updating the files — you'll be asked to approve again once they're ready.</p>
        </div>
      )}

      {prod.mpcOk && (
        <div style={{ borderTop: `1px solid ${K.line}`, padding: "12px 22px", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
          <span style={{ fontSize: 13, color: K.sub }}>Approved by <strong style={{ color: K.ink }}>{prod.mpcBy}</strong> on {fmtDate(prod.mpcOn)}{prod.mpcVia ? <span> — based on {valLabel(prod.mpcVia).toLowerCase()}</span> : null} — this approval is final.</span>
          <Stamp animate={justApproved}>MPC Approved · {prod.mpcBy} · {fmtDate(prod.mpcOn)}</Stamp>
        </div>
      )}

      {prod.files.length > 0 && (
        <div style={{ borderTop: `1px solid ${K.line}`, padding: "12px 22px", display: "flex", gap: 16, flexWrap: "wrap" }}>
          {prod.files.map((f) => (
            f.url
              ? <ExtLink key={f.name} href={f.url} style={{ fontSize: 13 }}>↓ {f.name} <span style={{ color: K.sub, fontWeight: 400 }}>({f.kind}{f.date ? " · " + fmtDate(f.date) : ""})</span></ExtLink>
              : <a key={f.name} className="k-link" href="#" onClick={(e) => e.preventDefault()} style={{ fontSize: 13 }}>↓ {f.name} <span style={{ color: K.sub, fontWeight: 400 }}>({f.kind} · {fmtDate(f.date)})</span></a>
          ))}
          {prod.transportIds.length > 0 && <span style={{ fontSize: 13, color: K.teal, fontWeight: 600 }}>⛴ Shipment {fmtDate(prod.prodEnd)} — docs available</span>}
        </div>
      )}

      {modal === "approve" && <ApproveModal prod={prod} partner={partner} onClose={() => setModal(null)} onConfirm={approve} />}
      {modal === "changes" && <ChangesModal prod={prod} onClose={() => setModal(null)} onConfirm={requestChanges} />}
      {modal === "basic" && <BasicDataModal prod={prod} onClose={() => setModal(null)} />}
    </div>
  );
}

function ShippingBlock({ title, hint, value, partner, fieldKey, update, push }) {
  const [draft, setDraft] = React.useState(value);
  const [confirming, setConfirming] = React.useState(false);
  const [name, setName] = React.useState("");
  React.useEffect(() => setDraft(value), [value]);
  const dirty = draft !== value;
  const stale = monthsAgo(partner.confirmedOn) > 6;
  const empty = !value || !value.trim();

  const save = () => {
    update((db) => { db.partners.find((p) => p.id === partner.id)[fieldKey] = draft; });
    push("Shipping information saved.");
  };
  const confirm = () => {
    update((db) => {
      const p = db.partners.find((x) => x.id === partner.id);
      p.confirmedOn = todayIso(); p.confirmedBy = name.trim();
      db.log.unshift({ ts: nowStamp(), actor: `${name.trim()} (${partner.company.split(" ")[0]})`, action: "Shipping info confirmed", detail: title });
    });
    setConfirming(false); push("Thank you — information confirmed.");
  };

  return (
    <div className="k-card" data-todo-anchor={fieldKey} style={{ marginTop: 14, padding: "16px 22px" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 12, flexWrap: "wrap" }}>
        <div className="k-round" style={{ fontSize: 16, fontWeight: 700 }}>{title}</div>
        <span style={{ fontSize: 12, color: K.sub }}>
          {partner.confirmedOn ? `Last confirmed ${fmtDate(partner.confirmedOn)} by ${partner.confirmedBy}` : "Never confirmed"}
        </span>
      </div>
      <p style={{ margin: "4px 0 10px", fontSize: 12.5, color: K.sub }}>{hint}</p>
      <textarea className="k-textarea" rows={6} value={draft} placeholder="No information yet — please fill in." onChange={(e) => setDraft(e.target.value)}></textarea>
      {empty && !dirty && <Banner tone="red" style={{ marginTop: 10 }}>✕ Missing — required before shipping.</Banner>}
      {!empty && stale && <Banner tone="amber" style={{ marginTop: 10 }}>⚠ Confirmed more than 6 months ago — please review and confirm below.</Banner>}
      <div style={{ display: "flex", gap: 10, marginTop: 12, flexWrap: "wrap" }}>
        {dirty && <button className="k-btn k-btn-primary k-btn-sm" onClick={save}>Save changes</button>}
        {dirty && <button className="k-btn k-btn-ghost k-btn-sm" onClick={() => setDraft(value)}>Discard</button>}
        {!dirty && !empty && <button className="k-btn k-btn-ghost k-btn-sm" onClick={() => setConfirming(true)}>I confirm this information is accurate</button>}
      </div>
      {confirming && (
        <Modal title="Confirm shipping information" onClose={() => setConfirming(false)}>
          <p style={{ margin: "0 0 12px" }}>This stamps today's date on <strong>{title}</strong> so KODAMA and the factory know it's current.</p>
          <div className="k-label" style={{ marginBottom: 6 }}>Your full name</div>
          <input className="k-input" autoFocus placeholder="e.g. Laura Bianchi" value={name} onChange={(e) => setName(e.target.value)} />
          <div style={{ display: "flex", gap: 10, marginTop: 16, justifyContent: "flex-end" }}>
            <button className="k-btn k-btn-ghost" onClick={() => setConfirming(false)}>Cancel</button>
            <button className="k-btn k-btn-primary" disabled={name.trim().length < 3} onClick={confirm}>✓ Confirm</button>
          </div>
        </Modal>
      )}
    </div>
  );
}

function PartnerView({ db, update, partnerId, t }) {
  const [toasts, push] = useToasts();
  const partner = db.partners.find((p) => p.id === partnerId) || db.partners[0];
  const prods = db.productions
    .filter((p) => p.partnerId === partner.id && p.statut !== "Terminé")
    .map((p) => {
      const print = db.prints.find((x) => x.id === p.printId);
      return { ...p, game: print.game, printLabel: print.label, gameLabel: `${print.game} · ${print.label}`, pallets: palletInfo(p.qty, db.basicData[print.gameId]), basic: db.basicData[print.gameId] };
    });
  const actionCount = prods.filter(needsApproval).length;
  const sorted = [...prods].sort((a, b) => needsApproval(b) - needsApproval(a));
  // Au-delà de 3 productions en cours, on regroupe par jeu pour s'y retrouver
  const gameGroups = [];
  sorted.forEach((p) => {
    let g = gameGroups.find((x) => x.game === p.game);
    if (!g) { g = { game: p.game, prods: [] }; gameGroups.push(g); }
    g.prods.push(p);
  });
  const grouped = sorted.length > 3 && gameGroups.length > 1;
  const history = db.productions
    .filter((p) => p.partnerId === partner.id && p.statut === "Terminé")
    .map((p) => { const print = db.prints.find((x) => x.id === p.printId); return { ...p, game: print ? print.game : "?", printLabel: print ? print.label : "" }; })
    .sort((a, b) => String(b.prodEnd || "").localeCompare(String(a.prodEnd || "")));
  const [showHistory, setShowHistory] = React.useState(false);

  return (
    <div style={{ minHeight: "100vh", background: K.bg }}>
      <TopBar title="Production Portal" right={
        <div><div style={{ fontWeight: 700, color: "#FFF" }}>{partner.company.toUpperCase()}</div>
        <div style={{ fontSize: 12, color: "rgba(255,255,255,0.65)" }}>{partner.country} {partner.flag}</div></div>
      } />
      <div style={{ padding: "28px 44px 48px", maxWidth: 1180, margin: "0 auto" }}>
        <h1 className="k-round" style={{ fontSize: 30, fontWeight: 700, margin: 0 }}>{greetingFor(partner, t)}, {firstName(partner)}!</h1>
        <p style={{ color: K.sub, margin: "2px 0 0" }}>
          {prods.length} production{prods.length > 1 ? "s" : ""} in progress
          {actionCount > 0 ? <span> — <strong style={{ color: K.pink }}>{actionCount} need{actionCount > 1 ? "" : "s"} your MPC approval</strong></span> : <span> — nothing needs your attention right now ✓</span>}.
        </p>

        <TodoRecap prods={sorted} partner={partner} />

        <SectionLabel>Your productions</SectionLabel>
        {grouped ? gameGroups.map((g) => (
          <div key={g.game} style={{ marginTop: 22 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 14, flexWrap: "wrap" }}>
              <div className="k-round" style={{ fontSize: 19, fontWeight: 700, padding: "3px 14px", borderRadius: 10, background: gameColor(g.game).fg, color: "#FFF" }}>{g.game}</div>
              <StateCounters counts={stateCounts(g.prods)} labels={{ ok: "MPC approved", waiting: "awaiting MPC", changes: "changes requested" }} />
              <StateBar counts={stateCounts(g.prods)} height={6} style={{ flex: 1, minWidth: 70, maxWidth: 280 }} />
            </div>
            {g.prods.map((p) => <ProdCard key={p.id} prod={p} partner={partner} update={update} push={push} />)}
          </div>
        )) : sorted.map((p) => <ProdCard key={p.id} prod={p} partner={partner} update={update} push={push} />)}
        {sorted.length === 0 && <div className="k-card" style={{ marginTop: 12, padding: "22px", color: K.sub, textAlign: "center" }}>No production in progress right now.</div>}

        {history.length > 0 && (
          <div style={{ marginTop: 18 }}>
            <button onClick={() => setShowHistory(!showHistory)} style={{ background: "none", border: `1.5px dashed ${K.line}`, borderRadius: 10, padding: "9px 16px", cursor: "pointer", fontFamily: K.font, fontSize: 13, fontWeight: 700, color: K.sub, width: "100%", textAlign: "left" }}>
              <span style={{ display: "inline-block", transform: showHistory ? "rotate(90deg)" : "none", transition: "transform .15s", marginRight: 8 }}>▸</span>
              Past productions — {history.length} completed
            </button>
            {showHistory && (
              <div className="k-card" style={{ marginTop: 10, overflow: "hidden" }}>
                <table style={{ width: "100%", borderCollapse: "collapse" }}>
                  <tbody>
                    {history.map((p, i) => (
                      <tr key={p.id}>
                        <td style={{ padding: "9px 16px", borderTop: i === 0 ? "none" : `1px solid ${K.line}`, fontWeight: 700, fontSize: 13 }}>{p.game} <span style={{ color: K.sub, fontWeight: 500 }}>· {p.printLabel}</span></td>
                        <td style={{ padding: "9px 16px", borderTop: i === 0 ? "none" : `1px solid ${K.line}`, textAlign: "right", fontFamily: K.mono, fontSize: 12.5 }}>{(p.qty || 0).toLocaleString("fr-FR").replace(/\u202f/g, " ")} units</td>
                        <td style={{ padding: "9px 16px", borderTop: i === 0 ? "none" : `1px solid ${K.line}`, textAlign: "right", fontSize: 12.5, color: K.sub, whiteSpace: "nowrap" }}>{p.prodEnd ? "finished " + fmtDate(p.prodEnd) : "✓ completed"}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        )}

        <SectionLabel style={{ marginTop: 38 }}>Your shipping information</SectionLabel>
        <ShippingBlock title="Consignee & Notify Party" fieldKey="consignee" value={partner.consignee} partner={partner} update={update} push={push}
          hint="Used on the Bill of Lading and customs documents for every shipment. Kept exactly as written." />
        <ShippingBlock title="Pre-production samples address" fieldKey="preprod" value={partner.preprod} partner={partner} update={update} push={push}
          hint="Where the factory sends your advance copies before mass production ships." />

        <div style={{ marginTop: 34, textAlign: "center", fontSize: 12.5, color: K.sub }}>
          <span className="k-round" style={{ fontWeight: 700, background: K.grad, WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent" }}>Playful spirit.</span>
          &nbsp; Questions? Just reply to your usual KODAMA contact — we read everything.
        </div>
      </div>
      <ToastHost toasts={toasts} />
    </div>
  );
}
Object.assign(window, { PartnerView, greetingFor, valLabel });
