/* marketplace-screens.jsx — the Marketplace environment.
   Source external capacity and content and leverage it into the own account:
   · External trainers  → "Add to my trainers" (lands in Trainers / Trainer KPIs,
     day rate feeds the cohort business case)
   · External products (courses & eLearning) → "Import" creates a real product in
     the shared store (Products screen), licence/exam cost prefilled
   · External course plannings → "Resell seats" creates a real cohort in the own
     delivery roadmap (My Cohorts board) with capacity = resold seats and the
     buy/sell economics in the course notes; own plannings can also be uploaded.
   The provider catalog is demo/seed data (no live provider integrations in this
   POV) and is hidden when demo content is off; uploads + acquisitions are real
   per-account data (VHStore "marketplace.acquired"). */

/* ── external provider catalog (fictional providers, demo-gated) ── */
const MP_TRAINERS = [
  { id:"mpt1", name:"Ingrid Svensson",  ti:"IS", bg:"#0e7490", provider:"NordicPM Institute",     courses:["IPMA-C","IPMA-B","MSP"],        dayRate:1500, avgRating:4.8, sessions:34, learners:410, completion:91, nps:78, langs:"EN · SV" },
  { id:"mpt2", name:"Carlos Mendes",    ti:"CM", bg:"#b45309", provider:"Skillbridge Collective", courses:["ITIL 4","SIAM","VeriSM"],        dayRate:1250, avgRating:4.6, sessions:28, learners:355, completion:87, nps:71, langs:"EN · PT · ES" },
  { id:"mpt3", name:"Aisha Rahman",     ti:"AR", bg:"#7c3aed", provider:"AgileMinds Academy",     courses:["SAFe","Scrum","Kanban"],         dayRate:1400, avgRating:4.9, sessions:41, learners:520, completion:93, nps:85, langs:"EN" },
  { id:"mpt4", name:"Jan Kowalski",     ti:"JK", bg:"#16a34a", provider:"TrainWorks EU",          courses:["PRINCE2 F","PRINCE2 P","P3O"],   dayRate:1100, avgRating:4.5, sessions:22, learners:260, completion:84, nps:66, langs:"EN · PL · DE" },
  { id:"mpt5", name:"Marie Dubois",     ti:"MD", bg:"#db2777", provider:"CertPartners BV",        courses:["LSS Green","LSS Black"],         dayRate:1350, avgRating:4.7, sessions:30, learners:340, completion:89, nps:74, langs:"EN · FR · NL" },
  { id:"mpt6", name:"Stefan Bauer",     ti:"SB", bg:"#3730a3", provider:"TrainWorks EU",          courses:["TOGAF","COBIT","ISO 27001"],     dayRate:1550, avgRating:4.7, sessions:26, learners:290, completion:88, nps:73, langs:"EN · DE" },
].map(t => ({ __seed:true, ...t }));

const MP_PRODUCTS = [
  { id:"mpp1", title:"OBASHI® Foundation",                    type:"Course",    provider:"Skillbridge Collective", level:"Foundation",   days:2, licenseCost:180, examCost:250, listPrice:1295, rating:4.6, icon:"layers",  color:"#0e7490", blurb:"Business & IT mapping method — licensed courseware incl. trainer pack." },
  { id:"mpp2", title:"Cyber Resilience RESILIA®",             type:"Course",    provider:"CertPartners BV",        level:"Foundation",   days:3, licenseCost:210, examCost:290, listPrice:1595, rating:4.5, icon:"shield",  color:"#b91c1c", blurb:"Cyber resilience best practice aligned with ITIL — full slide deck + labs." },
  { id:"mpp3", title:"Data Literacy Essentials (eLearning)",  type:"eLearning", provider:"AgileMinds Academy",     level:"Foundation",   days:0, licenseCost:95,  examCost:0,   listPrice:395,  rating:4.7, icon:"monitor", color:"#9333ea", blurb:"8h self-paced eLearning, SCORM package, per-seat licence." },
  { id:"mpp4", title:"Sustainable IT Foundation",             type:"Course",    provider:"NordicPM Institute",     level:"Foundation",   days:2, licenseCost:165, examCost:230, listPrice:1195, rating:4.4, icon:"globe",   color:"#16a34a", blurb:"Green IT strategy & reporting — courseware + case studies." },
  { id:"mpp5", title:"Kanban System Design (eLearning)",      type:"eLearning", provider:"AgileMinds Academy",     level:"Advanced",     days:0, licenseCost:120, examCost:0,   listPrice:495,  rating:4.8, icon:"pipeline",color:"#ea580c", blurb:"12h self-paced with simulations, per-seat licence, EN/NL." },
  { id:"mpp6", title:"AI Governance Practitioner",            type:"Course",    provider:"TrainWorks EU",          level:"Practitioner", days:3, licenseCost:260, examCost:340, listPrice:1895, rating:4.6, icon:"wand",    color:"#3730a3", blurb:"EU AI Act aligned governance training — licensed slides, cases, mock exam." },
].map(p => ({ __seed:true, ...p }));

const MP_PLANNINGS = [
  { id:"mpl1", provider:"TrainWorks EU",          course:"PRINCE2® Foundation",        date:"2026-09-14", days:3, location:"Utrecht",    seats:8,  buyPerSeat:520, listPerSeat:1495 },
  { id:"mpl2", provider:"AgileMinds Academy",     course:"Leading SAFe®",              date:"2026-09-28", days:2, location:"Amsterdam",  seats:6,  buyPerSeat:640, listPerSeat:1795 },
  { id:"mpl3", provider:"CertPartners BV",        course:"Lean Six Sigma Green Belt",  date:"2026-10-12", days:5, location:"Rotterdam",  seats:10, buyPerSeat:780, listPerSeat:2195 },
  { id:"mpl4", provider:"NordicPM Institute",     course:"IPMA-C Certification",       date:"2026-10-26", days:4, location:"Online",     seats:12, buyPerSeat:590, listPerSeat:1695 },
  { id:"mpl5", provider:"Skillbridge Collective", course:"ITIL® 4 Foundation",         date:"2026-11-09", days:2, location:"Eindhoven",  seats:9,  buyPerSeat:430, listPerSeat:1295 },
  { id:"mpl6", provider:"TrainWorks EU",          course:"TOGAF® Enterprise Architecture", date:"2026-11-23", days:4, location:"Online", seats:14, buyPerSeat:820, listPerSeat:2395 },
].map(p => ({ __seed:true, ...p }));

/* ── requests board ("place an advertisement") ──────────────────────────────
   The demand side of the marketplace: an organisation posts what it is LOOKING
   FOR — a trainer, a training, seats on a run or an eLearning — with the specs
   (subject, level, language, location, period, days, candidates, budget,
   requirements). Seed ads are demo-gated; your own ads are real per-account data
   stored with the rest of the marketplace record. */
const MP_AD_KINDS = ["Trainer", "Training", "Seats", "eLearning"];
const MP_ADS = [
  { id:"mpa1", kind:"Trainer", title:"PRINCE2® Practitioner trainer wanted", subject:"PRINCE2® Practitioner", level:"Practitioner",
    language:"Dutch · English", location:"Utrecht", from:"2026-10-05", to:"2026-10-09", days:3, seats:12, budget:1200, budgetUnit:"per day",
    requirements:"PeopleCert accredited · 5+ years delivery experience", deadline:"2026-08-31", org:"TrainWorks EU", contact:"sourcing@trainworks.eu",
    notes:"In-company run for a public-sector client. Dutch delivery, English materials." },
  { id:"mpa2", kind:"Seats", title:"Looking for 6 seats — Leading SAFe®", subject:"SAFe® Agilist (Leading SAFe®)", level:"Advanced",
    language:"English", location:"Randstad or Online", from:"2026-09-01", to:"2026-11-30", days:2, seats:6, budget:900, budgetUnit:"per seat",
    requirements:"Certified SPC trainer · exam voucher included", deadline:"2026-08-15", org:"CertPartners BV", contact:"buying@certpartners.nl",
    notes:"Our own run did not fill; we want to place 6 candidates on someone else's scheduled course." },
  { id:"mpa3", kind:"Training", title:"AI Governance course licence sought", subject:"AI Governance & Ethics", level:"Foundation",
    language:"English", location:"Licence / courseware", from:"", to:"", days:2, seats:0, budget:250, budgetUnit:"per candidate",
    requirements:"EU AI Act aligned · slides + cases + mock exam, white-label allowed", deadline:"2026-09-15", org:"NordicPM Institute", contact:"partners@nordicpm.se",
    notes:"We have demand but no material; looking to license rather than build." },
  { id:"mpa4", kind:"Trainer", title:"Lean Six Sigma Black Belt trainer (freelance)", subject:"Lean Six Sigma Black Belt", level:"Advanced",
    language:"English · German", location:"Eindhoven", from:"2026-11-09", to:"2026-11-13", days:5, seats:8, budget:1500, budgetUnit:"per day",
    requirements:"Master Black Belt · manufacturing case experience", deadline:"2026-09-30", org:"Skillbridge Collective", contact:"talent@skillbridge.io",
    notes:"Five consecutive days on site, materials provided by us." },
].map(a => ({ __seed:true, status:"open", ...a }));

const MP_KEY = "marketplace.acquired";
function mpEuro(n) { return "€" + Number(n || 0).toLocaleString("nl-NL"); }
function mpBlankAcq() { return { trainers: [], products: [], resold: [], uploads: [], ads: [] }; }
function mpAdPeriod(ad) {
  if (ad.from && ad.to) return ad.from + " → " + ad.to;
  return ad.from || ad.to || "Period flexible";
}

/* Merge acquired external trainers into the shared trainer roster (Trainers +
   Trainer KPIs read window.TRAINER_ROSTER). No __seed flag → they stay visible
   with demo content off: they are real acquisitions of this account. */
function mpRosterEntry(t) {
  return { name: t.name, ti: t.ti, bg: t.bg, sessions: t.sessions || 0, learners: t.learners || 0,
    avgRating: t.avgRating || 0, completion: t.completion || 0, nps: t.nps || 0, dayRate: t.dayRate || 0,
    courses: t.courses || [], external: true, provider: t.provider };
}
function mpMergeRoster(list) {
  const roster = window.TRAINER_ROSTER;
  if (!Array.isArray(roster)) return;
  (list || []).forEach(t => { if (!roster.some(r => r.name === t.name)) roster.push(mpRosterEntry(t)); });
}
async function __mpBoot() {
  try { const acq = await window.VHStore.get(MP_KEY, null); if (acq) mpMergeRoster(acq.trainers); } catch (e) {}
}
if (window.AUTH_USER) __mpBoot(); else window.addEventListener("vh-auth", __mpBoot, { once: true });

/* ── small bits ── */
function MPStars({ val }) {
  return <span style={{ fontSize: 12.5, fontWeight: 700, color: "#b45309", whiteSpace: "nowrap" }}>★ {Number(val || 0).toFixed(1)}</span>;
}
function MPProviderChip({ name }) {
  return <span style={{ background: "var(--surface-3)", borderRadius: 6, padding: "2px 8px", fontSize: 11.5, fontWeight: 700, color: "var(--ink-2)" }}>{name}</span>;
}
function MPModal({ title, onClose, children, width }) {
  return (
    <div style={{ position: "fixed", inset: 0, background: "rgba(13,26,52,.45)", zIndex: 320, display: "grid", placeItems: "center", padding: 20 }} onClick={onClose}>
      <div className="card" style={{ width: width || 460, maxWidth: "94vw", maxHeight: "88vh", overflowY: "auto", padding: 22 }} onClick={e => e.stopPropagation()}>
        <div className="between" style={{ marginBottom: 14 }}>
          <h3 style={{ fontSize: 16, fontWeight: 800 }}>{title}</h3>
          <button onClick={onClose} style={{ background: "none", border: "none", cursor: "pointer", padding: 4 }}><Icon name="x" size={16} /></button>
        </div>
        {children}
      </div>
    </div>
  );
}
function MPField({ label, children }) {
  return <label style={{ display: "block", marginBottom: 11 }}>
    <div style={{ fontSize: 11.5, fontWeight: 700, textTransform: "uppercase", letterSpacing: ".06em", color: "var(--ink-3)", marginBottom: 4 }}>{label}</div>
    {children}
  </label>;
}
const mpInp = { width: "100%", padding: "9px 11px", borderRadius: 9, border: "1.5px solid var(--line)", fontSize: 13.5, background: "var(--surface)", color: "var(--ink)" };

/* ── resell modal: seats + price → cohort in the delivery roadmap ── */
function MPResellModal({ planning, onClose, onDone, toast }) {
  const [seats, setSeats] = useState(Math.min(6, planning.seats));
  const [price, setPrice] = useState(planning.listPerSeat);
  const [busy, setBusy] = useState(false);
  const s = Math.max(1, Math.min(Number(seats) || 1, planning.seats));
  const p = Math.max(0, Number(price) || 0);
  const cost = s * planning.buyPerSeat, revenue = s * p, margin = revenue - cost;
  async function confirm() {
    if (busy) return; setBusy(true);
    try {
      const notes = "Marketplace resale · " + planning.provider + " runs this training (" + planning.location + "); we resell " + s +
        " seats — buy " + mpEuro(planning.buyPerSeat) + "/seat, sell " + mpEuro(p) + "/seat, margin " + mpEuro(margin) + ".";
      const c = await window.VHCohorts.create({
        name: planning.course + " · resold seats (" + planning.provider + ")",
        course: planning.course, capacity: s, start_at: cohEpoch(planning.date, "09:00"),
        incompany: false, material: "External — delivered by " + planning.provider, notes: notes,
      });
      onDone({ id: "rs-" + c.id, cohortId: c.id, planningId: planning.id, provider: planning.provider, course: planning.course, date: planning.date, seats: s, buyPerSeat: planning.buyPerSeat, sellPerSeat: p });
      toast("Cohort created in your delivery roadmap · voucher " + c.voucher, "check");
      onClose();
    } catch (e) { toast(e.message || "Could not create the cohort", "x"); }
    setBusy(false);
  }
  return (
    <MPModal title={"Resell seats — " + planning.course} onClose={onClose}>
      <div style={{ fontSize: 13, color: "var(--ink-2)", marginBottom: 14 }}>
        {planning.provider} · {planning.date} · {planning.location} · {planning.seats} seats on offer at {mpEuro(planning.buyPerSeat)}/seat.
        Reselling creates a cohort on your My&nbsp;Cohorts board — the provider delivers, you enrol your own candidates.
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <MPField label={"Seats to resell (max " + planning.seats + ")"}>
          <input type="number" min="1" max={planning.seats} value={seats} onChange={e => setSeats(e.target.value)} style={mpInp} />
        </MPField>
        <MPField label="Your price per seat (€)">
          <input type="number" min="0" value={price} onChange={e => setPrice(e.target.value)} style={mpInp} />
        </MPField>
      </div>
      <div style={{ background: "var(--surface-3)", borderRadius: 10, padding: "12px 14px", fontSize: 13, display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8, marginBottom: 16 }}>
        <div><div style={{ fontSize: 11, color: "var(--ink-3)", fontWeight: 700 }}>BUY</div><div style={{ fontWeight: 800 }}>{mpEuro(cost)}</div></div>
        <div><div style={{ fontSize: 11, color: "var(--ink-3)", fontWeight: 700 }}>REVENUE</div><div style={{ fontWeight: 800 }}>{mpEuro(revenue)}</div></div>
        <div><div style={{ fontSize: 11, color: "var(--ink-3)", fontWeight: 700 }}>MARGIN</div><div style={{ fontWeight: 800, color: margin >= 0 ? "#2e7d32" : "#b91c1c" }}>{mpEuro(margin)}{revenue > 0 ? " · " + Math.round(margin / revenue * 100) + "%" : ""}</div></div>
      </div>
      <button className="btn btn-acc" style={{ width: "100%" }} disabled={busy} onClick={confirm}><Icon name="plus" size={14} />{busy ? "Creating cohort…" : "Add to my delivery roadmap"}</button>
    </MPModal>
  );
}

/* ── upload own external planning ── */
function MPUploadModal({ onClose, onDone }) {
  const [v, setV] = useState({ provider: "", course: "", date: "", location: "", seats: "", buyPerSeat: "", listPerSeat: "" });
  const set = (k) => (e) => setV(o => ({ ...o, [k]: e.target.value }));
  const ok = v.provider.trim() && v.course.trim() && v.date && Number(v.seats) > 0;
  return (
    <MPModal title="Upload an external course planning" onClose={onClose}>
      <div style={{ fontSize: 13, color: "var(--ink-2)", marginBottom: 14 }}>Add a planning you sourced yourself (provider offer, partner mailing, …). It appears under Course plannings and can be resold into your roadmap like any catalog run.</div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <MPField label="Provider"><input value={v.provider} onChange={set("provider")} style={mpInp} placeholder="Provider name" /></MPField>
        <MPField label="Course"><input value={v.course} onChange={set("course")} style={mpInp} placeholder="Course title" /></MPField>
        <MPField label="Start date"><input type="date" value={v.date} onChange={set("date")} style={mpInp} /></MPField>
        <MPField label="Location"><input value={v.location} onChange={set("location")} style={mpInp} placeholder="City or Online" /></MPField>
        <MPField label="Seats on offer"><input type="number" min="1" value={v.seats} onChange={set("seats")} style={mpInp} /></MPField>
        <MPField label="Buy price / seat (€)"><input type="number" min="0" value={v.buyPerSeat} onChange={set("buyPerSeat")} style={mpInp} /></MPField>
        <MPField label="List price / seat (€)"><input type="number" min="0" value={v.listPerSeat} onChange={set("listPerSeat")} style={mpInp} /></MPField>
      </div>
      <button className="btn btn-acc" style={{ width: "100%" }} disabled={!ok}
        onClick={() => { onDone({ id: "up-" + Date.now(), uploaded: true, provider: v.provider.trim(), course: v.course.trim(), date: v.date, location: v.location.trim() || "—", days: 0, seats: Number(v.seats), buyPerSeat: Number(v.buyPerSeat) || 0, listPerSeat: Number(v.listPerSeat) || 0 }); onClose(); }}>
        <Icon name="plus" size={14} />Add planning
      </button>
    </MPModal>
  );
}

/* ── place an advertisement: post a request with its specs ── */
function MPAdModal({ onClose, onDone }) {
  const [v, setV] = useState({ kind: "Trainer", title: "", subject: "", level: "Any", language: "", location: "",
    from: "", to: "", days: "", seats: "", budget: "", budgetUnit: "per day", requirements: "", notes: "", deadline: "" });
  const set = (k) => (e) => setV(o => ({ ...o, [k]: e.target.value }));
  const ok = v.title.trim() && v.subject.trim();
  const me = (window.AUTH_USER && (window.AUTH_USER.name || window.AUTH_USER.email)) || "My organisation";
  const myMail = (window.AUTH_USER && window.AUTH_USER.email) || "";
  return (
    <MPModal title="Place an advertisement" onClose={onClose} width={620}>
      <div style={{ fontSize: 13, color: "var(--ink-2)", marginBottom: 14 }}>
        Post what you are <b>looking for</b> — a trainer, a training, seats on someone else’s run, or an eLearning licence — with the specs providers need to answer.
      </div>
      <MPField label="I am looking for">
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
          {MP_AD_KINDS.map(k => (
            <button key={k} className={"filter-chip" + (v.kind === k ? " on" : "")} onClick={() => setV(o => ({ ...o, kind: k }))}>{k}</button>
          ))}
        </div>
      </MPField>
      <MPField label="Headline"><input value={v.title} onChange={set("title")} style={mpInp} placeholder="e.g. PRINCE2® Practitioner trainer wanted" /></MPField>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <MPField label="Subject / course"><input value={v.subject} onChange={set("subject")} style={mpInp} placeholder="e.g. PRINCE2® Practitioner" /></MPField>
        <MPField label="Level">
          <select value={v.level} onChange={set("level")} style={mpInp}>
            {["Any", "Foundation", "Practitioner", "Advanced", "Expert"].map(l => <option key={l}>{l}</option>)}
          </select>
        </MPField>
        <MPField label="Language(s)"><input value={v.language} onChange={set("language")} style={mpInp} placeholder="e.g. Dutch · English" /></MPField>
        <MPField label="Location"><input value={v.location} onChange={set("location")} style={mpInp} placeholder="City, Online or In-company" /></MPField>
        <MPField label="Preferred from"><input type="date" value={v.from} onChange={set("from")} style={mpInp} /></MPField>
        <MPField label="Preferred until"><input type="date" value={v.to} onChange={set("to")} style={mpInp} /></MPField>
        <MPField label="Duration (days)"><input type="number" min="0" value={v.days} onChange={set("days")} style={mpInp} placeholder="3" /></MPField>
        <MPField label="Candidates / seats"><input type="number" min="0" value={v.seats} onChange={set("seats")} style={mpInp} placeholder="12" /></MPField>
        <MPField label="Budget (€)"><input type="number" min="0" value={v.budget} onChange={set("budget")} style={mpInp} placeholder="1200" /></MPField>
        <MPField label="Budget basis">
          <select value={v.budgetUnit} onChange={set("budgetUnit")} style={mpInp}>
            {["per day", "per seat", "per candidate", "total"].map(u => <option key={u}>{u}</option>)}
          </select>
        </MPField>
      </div>
      <MPField label="Requirements / accreditation"><input value={v.requirements} onChange={set("requirements")} style={mpInp} placeholder="e.g. PeopleCert accredited · 5+ years experience" /></MPField>
      <MPField label="Description"><textarea value={v.notes} onChange={set("notes")} rows={3} style={{ ...mpInp, resize: "vertical" }} placeholder="Context, client type, materials provided…" /></MPField>
      <MPField label="Respond by"><input type="date" value={v.deadline} onChange={set("deadline")} style={mpInp} /></MPField>
      <button className="btn btn-acc" style={{ width: "100%" }} disabled={!ok}
        onClick={() => {
          onDone({ id: "ad-" + Date.now(), kind: v.kind, title: v.title.trim(), subject: v.subject.trim(), level: v.level,
            language: v.language.trim(), location: v.location.trim(), from: v.from, to: v.to,
            days: Number(v.days) || 0, seats: Number(v.seats) || 0, budget: Number(v.budget) || 0, budgetUnit: v.budgetUnit,
            requirements: v.requirements.trim(), notes: v.notes.trim(), deadline: v.deadline,
            org: me, contact: myMail, mine: true, status: "open", created: new Date().toISOString().slice(0, 10) });
          onClose();
        }}>
        <Icon name="plus" size={14} />Publish advertisement
      </button>
    </MPModal>
  );
}

/* ── one request card ── */
function MPAdCard({ ad, onRespond, onClose_, onDelete }) {
  const closed = ad.status === "closed";
  const spec = [
    ad.level && ad.level !== "Any" ? ad.level : null,
    ad.language || null,
    ad.location || null,
    mpAdPeriod(ad),
    ad.days ? ad.days + " days" : null,
    ad.seats ? ad.seats + (ad.kind === "Seats" ? " seats" : " candidates") : null,
  ].filter(Boolean);
  return (
    <div className="card" style={{ padding: 18, opacity: closed ? .6 : 1 }}>
      <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 8, flexWrap: "wrap" }}>
        <span style={{ fontSize: 10, fontWeight: 800, letterSpacing: ".06em", padding: "2px 8px", borderRadius: 999, background: "rgba(18,129,196,.12)", color: "#1281c4" }}>{ad.kind.toUpperCase()}</span>
        {ad.mine && <span style={{ fontSize: 10, fontWeight: 800, letterSpacing: ".06em", padding: "2px 8px", borderRadius: 999, background: "#e8f5e9", color: "#2e7d32" }}>YOUR AD</span>}
        {closed && <span style={{ fontSize: 10, fontWeight: 800, letterSpacing: ".06em", padding: "2px 8px", borderRadius: 999, background: "var(--surface-3)", color: "var(--ink-3)" }}>CLOSED</span>}
        <span style={{ marginLeft: "auto", fontSize: 11.5, color: "var(--ink-3)" }}>{ad.deadline ? "respond by " + ad.deadline : ""}</span>
      </div>
      <div style={{ fontWeight: 800, fontSize: 14.5, marginBottom: 2 }}>{ad.title}</div>
      <div style={{ fontSize: 12.5, color: "var(--ink-2)", marginBottom: 9 }}>{ad.subject}</div>
      <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 9 }}>
        {spec.map((s, i) => <span key={i} style={{ background: "var(--surface-3)", borderRadius: 6, padding: "2px 8px", fontSize: 11.5, fontWeight: 600, color: "var(--ink-2)" }}>{s}</span>)}
      </div>
      {ad.requirements && <div style={{ fontSize: 12.5, color: "var(--ink-2)", marginBottom: 6 }}><b>Requires:</b> {ad.requirements}</div>}
      {ad.notes && <div style={{ fontSize: 12.5, color: "var(--ink-3)", marginBottom: 10 }}>{ad.notes}</div>}
      <div className="between" style={{ borderTop: "1px solid var(--line)", paddingTop: 10 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8, minWidth: 0 }}>
          <MPProviderChip name={ad.org} />
          {ad.budget > 0 && <span style={{ fontSize: 13, fontWeight: 800 }}>{mpEuro(ad.budget)}<span style={{ fontWeight: 600, color: "var(--ink-3)", fontSize: 11.5 }}> {ad.budgetUnit}</span></span>}
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          {ad.mine ? (
            <>
              {!closed && <button className="btn btn-outline" onClick={() => onClose_(ad)} title="Stop receiving responses"><Icon name="check" size={13} />Close</button>}
              <button className="btn btn-outline" onClick={() => onDelete(ad)} title="Delete this advertisement"><Icon name="x" size={13} /></button>
            </>
          ) : (
            <button className="btn btn-acc" disabled={closed} onClick={() => onRespond(ad)}><Icon name="mail" size={13} />Respond</button>
          )}
        </div>
      </div>
    </div>
  );
}

/* ── main screen ── */
function MarketplaceScreen({ toast, go }) {
  const demo = useDemoMode();
  const [tab, setTab] = useState("trainers");
  const [acq, setAcq] = useState(null);
  const [resellOf, setResellOf] = useState(null);
  const [uploadOpen, setUploadOpen] = useState(false);
  const [adOpen, setAdOpen] = useState(false);
  useEffect(() => { (async () => { const a = await window.VHStore.get(MP_KEY, null); setAcq({ ...mpBlankAcq(), ...(a || {}) }); })(); }, []);
  async function saveAcq(next) { setAcq(next); await window.VHStore.set(MP_KEY, next); }
  const a = acq || mpBlankAcq();

  const catTrainers = demo ? MP_TRAINERS : [];
  const catProducts = demo ? MP_PRODUCTS : [];
  const catPlannings = [...(demo ? MP_PLANNINGS : []), ...a.uploads];
  const catAds = [...(a.ads || []), ...(demo ? MP_ADS : [])];

  function respondAd(ad) {
    if (!ad.contact) { toast("No contact address on this advertisement", "info"); return; }
    const subject = encodeURIComponent("Response to your marketplace ad — " + ad.title);
    const body = encodeURIComponent("Hello " + ad.org + ",\n\nWe can help with your request for " + ad.subject + ".\n\n");
    try { window.location.href = "mailto:" + ad.contact + "?subject=" + subject + "&body=" + body; } catch (e) {}
    toast("Opening your email to respond", "mail");
  }
  async function closeAd(ad) {
    await saveAcq({ ...a, ads: (a.ads || []).map(x => x.id === ad.id ? { ...x, status: "closed" } : x) });
    toast("Advertisement closed", "check");
  }
  async function deleteAd(ad) {
    await saveAcq({ ...a, ads: (a.ads || []).filter(x => x.id !== ad.id) });
    toast("Advertisement removed", "check");
  }

  async function addTrainer(t) {
    if (a.trainers.some(x => x.id === t.id)) { toast("Already in your trainer pool", "check"); return; }
    const next = { ...a, trainers: [...a.trainers, t] };
    mpMergeRoster([t]);
    await saveAcq(next);
    toast(t.name + " added to your trainers", "check");
  }
  async function importProduct(p) {
    if (a.products.some(x => x.id === p.id)) { toast("Already imported", "check"); return; }
    const prod = { id: "mp-" + p.id, name: p.title, icon: p.icon, color: p.color, level: p.level, lang: "English",
      body: p.provider, price: mpEuro(p.listPrice), learners: 0, external: true, provider: p.provider,
      materialCost: p.licenseCost, examCost: p.examCost };
    const saved = await window.VHProducts.save([prod]);
    if (!saved) { toast("Could not import the product", "x"); return; }
    await saveAcq({ ...a, products: [...a.products, p] });
    toast(p.title + " imported into Products", "check");
  }
  async function removeTrainer(t) {
    const roster = window.TRAINER_ROSTER;
    if (Array.isArray(roster)) { const i = roster.findIndex(r => r.name === t.name && r.external); if (i >= 0) roster.splice(i, 1); }
    await saveAcq({ ...a, trainers: a.trainers.filter(x => x.id !== t.id) });
    toast(t.name + " removed", "check");
  }

  const empty = (msg) => (
    <div className="card" style={{ padding: "34px 24px", textAlign: "center", color: "var(--ink-3)", fontSize: 13.5 }}>{msg}</div>
  );
  const seg = (id, label, count) => (
    <button className={"segtab" + (tab === id ? " on" : "")} onClick={() => setTab(id)}>{label}{count != null && count > 0 ? " · " + count : ""}</button>
  );

  return (
    <div>
      <div className="between" style={{ marginBottom: 22 }}>
        <div className="page-head" style={{ marginBottom: 0 }}>
          <h1>Marketplace</h1>
          <p>Source external trainers, products and scheduled runs — and pull them into your own account.</p>
        </div>
        <div style={{ display: "flex", gap: 10 }}>
          <button className="btn btn-outline" onClick={() => setUploadOpen(true)}><Icon name="download" size={14} />Upload planning</button>
          <button className="btn btn-acc" onClick={() => setAdOpen(true)}><Icon name="plus" size={14} />Place an advertisement</button>
        </div>
      </div>
      <div className="segtabs" style={{ marginBottom: 20 }}>
        {seg("trainers", "External trainers")}
        {seg("products", "Courses & eLearning")}
        {seg("plannings", "Course plannings", catPlannings.length)}
        {seg("requests", "Requests & ads", catAds.length)}
        {seg("mine", "In your account", a.trainers.length + a.products.length + a.resold.length)}
      </div>

      {!demo && tab !== "mine" && catPlannings.length === 0 && tab === "plannings" && empty("No external plannings yet — provider integrations are not live in this POV. Upload a planning you sourced yourself with the button above.")}
      {!demo && (tab === "trainers" || tab === "products") && empty("No external providers connected — the provider catalog is demo content in this POV (switch demo content on to browse it). Acquired items stay under “In your account”.")}

      {tab === "trainers" && demo && (
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(320px, 1fr))", gap: 14 }}>
          {catTrainers.map(t => {
            const mine = a.trainers.some(x => x.id === t.id);
            return (
              <div key={t.id} className="card" style={{ padding: 18 }}>
                <div style={{ display: "flex", alignItems: "center", gap: 11, marginBottom: 10 }}>
                  <span style={{ width: 38, height: 38, borderRadius: "50%", flex: "none", background: t.bg, color: "#fff", fontWeight: 800, fontSize: 13, display: "grid", placeItems: "center" }}>{t.ti}</span>
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{ fontWeight: 800, fontSize: 14.5 }}>{t.name}</div>
                    <div style={{ fontSize: 12, color: "var(--ink-3)" }}>{t.langs} · {t.sessions} sessions · {t.learners} learners</div>
                  </div>
                  <MPStars val={t.avgRating} />
                </div>
                <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 10 }}>
                  <MPProviderChip name={t.provider} />
                  {t.courses.map(c => <span key={c} style={{ background: "var(--surface-3)", borderRadius: 6, padding: "2px 8px", fontSize: 11.5, fontWeight: 600, color: "var(--ink-3)" }}>{c}</span>)}
                </div>
                <div className="between">
                  <div style={{ fontSize: 13.5, fontWeight: 800 }}>{mpEuro(t.dayRate)}<span style={{ fontWeight: 600, color: "var(--ink-3)", fontSize: 12 }}> /day</span></div>
                  {mine
                    ? <button className="btn btn-outline" onClick={() => go && go("trainer-kpis")} title="Already in your pool — view in Trainer KPIs"><Icon name="check" size={13} />In your pool</button>
                    : <button className="btn btn-acc" onClick={() => addTrainer(t)}><Icon name="plus" size={13} />Add to my trainers</button>}
                </div>
              </div>
            );
          })}
        </div>
      )}

      {tab === "products" && demo && (
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(320px, 1fr))", gap: 14 }}>
          {catProducts.map(p => {
            const mine = a.products.some(x => x.id === p.id);
            return (
              <div key={p.id} className="card" style={{ padding: 18 }}>
                <div style={{ display: "flex", alignItems: "center", gap: 11, marginBottom: 8 }}>
                  <div style={{ width: 36, height: 36, borderRadius: 9, background: "var(--surface-3)", display: "grid", placeItems: "center", flex: "none" }}><Icon name={p.icon} size={17} style={{ color: p.color }} /></div>
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{ fontWeight: 800, fontSize: 14 }}>{p.title}</div>
                    <div style={{ fontSize: 12, color: "var(--ink-3)" }}>{p.type} · {p.level}{p.days ? " · " + p.days + " days" : ""}</div>
                  </div>
                  <MPStars val={p.rating} />
                </div>
                <div style={{ fontSize: 12.5, color: "var(--ink-2)", marginBottom: 10 }}>{p.blurb}</div>
                <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 10, alignItems: "center" }}>
                  <MPProviderChip name={p.provider} />
                  <span style={{ fontSize: 12, color: "var(--ink-3)" }}>licence {mpEuro(p.licenseCost)}/cand{p.examCost ? " · exam " + mpEuro(p.examCost) + "/cand" : ""}</span>
                </div>
                <div className="between">
                  <div style={{ fontSize: 13.5, fontWeight: 800 }}>{mpEuro(p.listPrice)}<span style={{ fontWeight: 600, color: "var(--ink-3)", fontSize: 12 }}> list</span></div>
                  {mine
                    ? <button className="btn btn-outline" onClick={() => go && go("products")} title="Imported — open Products"><Icon name="check" size={13} />Imported</button>
                    : <button className="btn btn-acc" onClick={() => importProduct(p)}><Icon name="download" size={13} />Import to my products</button>}
                </div>
              </div>
            );
          })}
        </div>
      )}

      {tab === "plannings" && catPlannings.length > 0 && (
        <div className="card">
          <table className="tbl">
            <thead><tr><th>Course</th><th>Provider</th><th>Date</th><th>Location</th><th>Seats</th><th>Buy / seat</th><th>List / seat</th><th></th></tr></thead>
            <tbody>
              {catPlannings.map(pl => {
                const sold = a.resold.filter(r => r.planningId === pl.id);
                return (
                  <tr key={pl.id}>
                    <td style={{ fontWeight: 700 }}>{pl.course}{pl.uploaded && <span style={{ marginLeft: 8, fontSize: 10, fontWeight: 800, letterSpacing: ".06em", color: "#0891b2", background: "rgba(8,145,178,.1)", borderRadius: 5, padding: "2px 6px" }}>UPLOADED</span>}</td>
                    <td><MPProviderChip name={pl.provider} /></td>
                    <td>{pl.date}</td>
                    <td>{pl.location}</td>
                    <td style={{ fontWeight: 700 }}>{pl.seats}</td>
                    <td>{mpEuro(pl.buyPerSeat)}</td>
                    <td>{mpEuro(pl.listPerSeat)}</td>
                    <td style={{ textAlign: "right", whiteSpace: "nowrap" }}>
                      {sold.length > 0 && <span style={{ fontSize: 11.5, fontWeight: 700, color: "#2e7d32", marginRight: 10 }} title="Already resold into your roadmap">{sold.reduce((s, r) => s + r.seats, 0)} seats resold</span>}
                      <button className="btn btn-acc" onClick={() => setResellOf(pl)}><Icon name="ticket" size={13} />Resell seats</button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}

      {tab === "requests" && (
        catAds.length === 0
          ? empty("No advertisements yet — press “Place an advertisement” to post what you are looking for (a trainer, a training, seats or an eLearning) with its specs.")
          : (
            <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(340px, 1fr))", gap: 14 }}>
              {catAds.map(ad => (
                <MPAdCard key={ad.id} ad={ad} onRespond={respondAd} onClose_={closeAd} onDelete={deleteAd} />
              ))}
            </div>
          )
      )}

      {tab === "mine" && (
        <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
          {a.trainers.length + a.products.length + a.resold.length === 0 && empty("Nothing pulled in yet — add a trainer, import a product or resell seats from a planning.")}
          {a.trainers.length > 0 && (
            <div className="card" style={{ padding: 18 }}>
              <div className="between" style={{ marginBottom: 10 }}>
                <div style={{ fontWeight: 800, fontSize: 14 }}>External trainers in your pool · {a.trainers.length}</div>
                <button className="btn btn-outline" onClick={() => go && go("trainer-kpis")}>Open Trainer KPIs<Icon name="arrowR" size={13} /></button>
              </div>
              {a.trainers.map(t => (
                <div key={t.id} className="between" style={{ padding: "8px 0", borderTop: "1px solid var(--line)", fontSize: 13 }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
                    <span style={{ width: 26, height: 26, borderRadius: "50%", background: t.bg, color: "#fff", fontWeight: 800, fontSize: 10, display: "grid", placeItems: "center" }}>{t.ti}</span>
                    <span style={{ fontWeight: 700 }}>{t.name}</span>
                    <MPProviderChip name={t.provider} />
                    <span style={{ color: "var(--ink-3)", fontSize: 12 }}>{mpEuro(t.dayRate)}/day</span>
                  </div>
                  <button className="btn btn-outline" onClick={() => removeTrainer(t)} title="Remove from your pool"><Icon name="x" size={12} /></button>
                </div>
              ))}
            </div>
          )}
          {a.products.length > 0 && (
            <div className="card" style={{ padding: 18 }}>
              <div className="between" style={{ marginBottom: 10 }}>
                <div style={{ fontWeight: 800, fontSize: 14 }}>Imported products · {a.products.length}</div>
                <button className="btn btn-outline" onClick={() => go && go("products")}>Open Products<Icon name="arrowR" size={13} /></button>
              </div>
              {a.products.map(p => (
                <div key={p.id} style={{ padding: "8px 0", borderTop: "1px solid var(--line)", fontSize: 13, display: "flex", alignItems: "center", gap: 9 }}>
                  <Icon name={p.icon} size={15} style={{ color: p.color }} />
                  <span style={{ fontWeight: 700 }}>{p.title}</span>
                  <MPProviderChip name={p.provider} />
                  <span style={{ color: "var(--ink-3)", fontSize: 12 }}>licence {mpEuro(p.licenseCost)}/cand</span>
                </div>
              ))}
            </div>
          )}
          {a.resold.length > 0 && (
            <div className="card" style={{ padding: 18 }}>
              <div className="between" style={{ marginBottom: 10 }}>
                <div style={{ fontWeight: 800, fontSize: 14 }}>Resold seats in your roadmap · {a.resold.length}</div>
                <button className="btn btn-outline" onClick={() => go && go("cohorts")}>Open My Cohorts<Icon name="arrowR" size={13} /></button>
              </div>
              {a.resold.map(r => (
                <div key={r.id} style={{ padding: "8px 0", borderTop: "1px solid var(--line)", fontSize: 13, display: "flex", alignItems: "center", gap: 9, flexWrap: "wrap" }}>
                  <span style={{ fontWeight: 700 }}>{r.course}</span>
                  <MPProviderChip name={r.provider} />
                  <span style={{ color: "var(--ink-3)", fontSize: 12 }}>{r.date} · {r.seats} seats · buy {mpEuro(r.buyPerSeat)} / sell {mpEuro(r.sellPerSeat)} per seat · margin {mpEuro((r.sellPerSeat - r.buyPerSeat) * r.seats)}</span>
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      {resellOf && <MPResellModal planning={resellOf} toast={toast} onClose={() => setResellOf(null)}
        onDone={async (r) => { await saveAcq({ ...a, resold: [...a.resold, r] }); }} />}
      {uploadOpen && <MPUploadModal onClose={() => setUploadOpen(false)}
        onDone={async (u) => { await saveAcq({ ...a, uploads: [...a.uploads, u] }); setTab("plannings"); toast("Planning added — you can now resell its seats", "check"); }} />}
      {adOpen && <MPAdModal onClose={() => setAdOpen(false)}
        onDone={async (ad) => { await saveAcq({ ...a, ads: [ad, ...(a.ads || [])] }); setTab("requests"); toast("Advertisement published on the marketplace", "check"); }} />}
    </div>
  );
}

Object.assign(window, { MarketplaceScreen });
