/* global React, Icon, Badge, Tag, Avatar, Button, Field, Toggle, Tabs, Segmented, PeriodPicker, Card, Metric, Modal, Pager,
   LineChart, BarChart, AreaChart, DonutCard, Gauge, Heatmap, Sparkline, ProgressBar, toast, StatusBadge */

var { useState: useState_ex, useMemo: useMemo_ex, useEffect: useEffect_ex } = React;

// ============================================================
// TRAVEL GROUPS — Enhanced with detail drawer
// ============================================================
function PageTravelGroupsEnhanced() {
  const [open, setOpen] = useState_ex(null);
  const [edit, setEdit] = useState_ex(null);
  const [del, setDel] = useState_ex(null);
  const [neu, setNeu] = useState_ex(false);
  const [q, setQ] = useState_ex("");
  const [page, setPage] = useState_ex(1);
  const [groups, setGroups] = useState_ex((window.MOCK && window.MOCK.TRAVEL_GROUPS) || []);
  // Real-data KPI block: fetch confirmed + cancelled bookings and
  // aggregate by agencies that belong to any group. The previous values
  // (6,842 / €4.28M / 284 / €68,400) were Claude-Design placeholders.
  const [kpi, setKpi] = useState_ex({ bookings: null, revenue: null, cancellations: null, savings: null });
  useEffect_ex(() => {
    if (!window.TrekkoAPI) return;
    window.TrekkoAPI.getTravelGroups().then((rows) => { if (rows && rows.length) setGroups(rows); });
  }, []);
  useEffect_ex(() => {
    if (!window.TrekkoAPI || !groups.length) return;
    // Build the set of agency identifiers that sit inside any travel group.
    const groupAgencyIds = new Set();
    groups.forEach((g) => {
      (g.agencies || []).forEach((a) => {
        const k = typeof a === "object" ? (a.id || a.uuid || a.name) : a;
        if (k != null) groupAgencyIds.add(String(k));
      });
    });
    if (!groupAgencyIds.size) return;
    Promise.all([
      window.TrekkoAPI.getBookings({ booking_status: "Upcoming" }).catch(() => []),
      window.TrekkoAPI.getBookings({ booking_status: "Ongoing" }).catch(() => []),
      window.TrekkoAPI.getBookings({ booking_status: "Completed" }).catch(() => []),
      window.TrekkoAPI.getBookings({ booking_status: "Cancelled" }).catch(() => []),
    ]).then(([up, ong, done, canc]) => {
      const live = [].concat(up || [], ong || [], done || []);
      const inGroup = (b) => {
        const k = String(b.agency_id || b.agencyId || b.agency || "");
        return groupAgencyIds.has(k);
      };
      const liveInGroup = live.filter(inGroup);
      const cancInGroup = (canc || []).filter(inGroup);
      const revenue = liveInGroup.reduce((a, b) => a + Number(b.amount || b.total_price || 0), 0);
      const savings = liveInGroup.reduce((a, b) => a + Number(b.trekko_rebooking_saving || b.agency_rebooking_saving || 0), 0);
      setKpi({
        bookings: liveInGroup.length,
        revenue: revenue,
        cancellations: cancInGroup.length,
        savings: savings,
      });
    });
  }, [groups]);
  const fmt = (n) => n == null ? "—" : Number(n).toLocaleString("en-US");
  const fmtEur = (n) => {
    if (n == null) return "—";
    const v = Number(n);
    if (v >= 1_000_000) return "€" + (v / 1_000_000).toFixed(2) + "M";
    if (v >= 1000) return "€" + Math.round(v / 1000).toLocaleString() + "k";
    return "€" + v.toLocaleString();
  };
  const PAGE = 8;

  const rows = groups.filter((g) =>
  !q || (g.name + g.code + g.description).toLowerCase().includes(q.toLowerCase())
  );
  const slice = rows.slice((page - 1) * PAGE, page * PAGE);

  return (
    <div data-comment-anchor="514b1cc14b-div-24-5">
      <div className="page-head">
        <div>
          <h1 className="page-head__title" data-comment-anchor="1ba710bc5d-h1-27-11">Travel Groups</h1>
          <div className="page-head__sub" data-comment-anchor="e85c1fae21-div-28-11">Networks of agencies sharing a Rappel rebate. Click a group to see members, agreement & performance.</div>
        </div>
        <div className="page-head__actions">
          <PeriodPicker value="month" onChange={() => {}} />
          <Button kind="secondary" icon={<Icon.Download />}>Export</Button>
          <Button kind="primary" icon={<Icon.Plus />} onClick={() => setNeu(true)}>Add group</Button>
        </div>
      </div>

      <div className="grid grid--4" style={{ marginBottom: 14 }}>
        <Metric accent label="Total groups" value={rows.length.toString()} delta="+1 this month" deltaDir="up" />
        <Metric label="Agencies linked" value={rows.reduce((a, g) => a + (g.agencies?.length || 0), 0).toString()} hint="Across all groups" />
        <Metric label="Average Rappel %" value={(rows.reduce((a, g) => a + g.rappel, 0) / Math.max(1, rows.length)).toFixed(1) + "%"} hint="Weighted by volume" />
        <Metric label="Rappel pool" value={kpi.revenue == null ? "—" : fmtEur((kpi.revenue || 0) * (rows.reduce((a, g) => a + g.rappel, 0) / Math.max(1, rows.length)) / 100)} hint="avg rappel % × group revenue" />
      </div>
      <div className="grid grid--4" style={{ marginBottom: 18 }}>
        <Metric label="Group bookings" value={fmt(kpi.bookings)} hint="Across all groups · all-time" />
        <Metric label="Group revenue" value={fmtEur(kpi.revenue)} hint="Sum of confirmed + completed" />
        <Metric label="Cancellations" value={fmt(kpi.cancellations)} hint={kpi.bookings ? Math.round(100 * (kpi.cancellations || 0) / Math.max(1, kpi.bookings + (kpi.cancellations || 0))) + "% cancel rate" : ""} />
        <Metric label="Rebookings saved" value={fmtEur(kpi.savings)} hint="Trekko + agency saving" />
      </div>

      <div className="filter-bar" data-comment-anchor="10579f8bbd-div-49-7">
        <input className="input input--search" placeholder="Search by group name, code or description…" style={{ width: 320 }} value={q} onChange={(e) => setQ(e.target.value)} />
        <select className="select"><option>All scopes</option><option>Iberia</option><option>DACH</option><option>UK</option><option>EU</option></select>
        <span className="spacer" />
        <Button kind="secondary" icon={<Icon.Filter />}>More filters</Button>
      </div>

      <div className="tbl-wrap tbl-wrap--linked">
        <table className="tbl">
          <thead>
            <tr>
              <th className="num">No</th><th>ID</th><th>Group code</th><th>Travel group name</th>
              <th>Description</th><th className="num">Sales (YTD)</th><th className="num">Rappel %</th><th className="num">Used in</th><th className="col-actions"></th>
            </tr>
          </thead>
          <tbody>
            {slice.map((g, i) =>
            <tr key={g.id} onClick={() => setOpen(g)} style={{ cursor: "pointer" }}>
                <td className="num mono muted">{(page - 1) * PAGE + i + 1}</td>
                <td className="mono">{g.id}</td>
                <td><Tag kind="hotel">{g.code}</Tag></td>
                <td className="bold">{g.name}</td>
                <td className="muted">{g.description}</td>
                <td className="num mono bold">{g.salesYtd != null ? fmtEur(g.salesYtd) : (g.sales_ytd != null ? fmtEur(g.sales_ytd) : "—")}</td>
                <td className="num mono"><Badge tone={g.rappel >= 5 ? "success" : g.rappel >= 3.5 ? "info" : "neutral"}>{g.rappel}%</Badge></td>
                <td className="num mono">{g.usedIn} {g.usedIn === 1 ? "agency" : "agencies"}</td>
                <td className="col-actions" onClick={(e) => e.stopPropagation()}>
                  <div className="row" style={{ gap: 4, justifyContent: "flex-end" }}>
                    <Button kind="ghost" size="sm" iconOnly icon={<Icon.Eye />} onClick={() => setOpen(g)} />
                    <Button kind="ghost" size="sm" iconOnly icon={<Icon.Edit />} onClick={() => setEdit(g)} />
                    <Button kind="ghost" size="sm" iconOnly icon={<Icon.Trash />} onClick={() => setDel(g)} />
                  </div>
                </td>
              </tr>
            )}
            {slice.length === 0 && <tr><td colSpan="8" className="tbl-empty">No groups match your search.</td></tr>}
          </tbody>
        </table>
      </div>
      <Pager page={page} pageSize={PAGE} total={rows.length} onPage={setPage} />

      <TravelGroupDrawer group={open} onClose={() => setOpen(null)} />
      <TGFormModal open={neu} onClose={() => setNeu(false)} />
      <TGFormModal open={!!edit} group={edit} onClose={() => setEdit(null)} />
      <TGDeleteModal group={del} onClose={() => setDel(null)} />
    </div>);

}

function TravelGroupDrawer({ group, onClose }) {
  const [agencies, setAgencies] = useState_ex((window.MOCK && window.MOCK.TRAVEL_AGENCIES) || []);
  useEffect_ex(() => {
    if (!group || !window.TrekkoAPI) return;
    window.TrekkoAPI.getAgencies().then((rows) => { if (rows && rows.length) setAgencies(rows); });
  }, [group]);
  if (!group) return null;
  const trend = [
  { label: "Jun", rappel: 2.8 }, { label: "Jul", rappel: 3.4 }, { label: "Aug", rappel: 3.8 },
  { label: "Sep", rappel: 3.1 }, { label: "Oct", rappel: 4.2 }, { label: "Nov", rappel: 4.6 },
  { label: "Dec", rappel: 4.1 }, { label: "Jan", rappel: 4.8 }, { label: "Feb", rappel: 5.2 },
  { label: "Mar", rappel: 5.8 }, { label: "Apr", rappel: 6.1 }, { label: "May", rappel: 6.4 }];


  return (
    <>
      <div className="drawer-veil" onClick={onClose} />
      <div className="drawer" style={{ width: "min(720px, 100vw)" }}>
        <div className="modal__head">
          <div>
            <div className="row" style={{ gap: 8 }}>
              <h3 className="modal__title">{group.name}</h3>
              <Tag kind="hotel">{group.code}</Tag>
              <Badge tone="success">Active</Badge>
            </div>
            <div className="muted tiny" style={{ marginTop: 2 }}>{group.id} · {group.description}</div>
          </div>
          <button className="modal__close" onClick={onClose}><Icon.X /></button>
        </div>
        <div className="modal__body">
          <div className="grid grid--3" style={{ gap: 12, marginBottom: 16 }}>
            <Metric label="Group bookings (YTD)" value={`${(group.usedIn * 142).toLocaleString()}`} mom="+9% MoM" momDir="up" yoy="+16% YoY" yoyDir="up" />
            <Metric label="Group revenue (YTD)" value={`€${(group.usedIn * 46).toFixed(0)}0k`} mom="+7% MoM" momDir="up" yoy="+19% YoY" yoyDir="up" accent />
            <Metric label="Group profit (YTD)" value={`€${(group.usedIn * 13.8).toFixed(0)}0k`} mom="+8% MoM" momDir="up" yoy="+21% YoY" yoyDir="up" />
          </div>

          <Card title="Bookings, revenue & profit by service segment" sub="Group-level breakdown" flush style={{ marginBottom: 16 }}>
            <table className="tbl" style={{ fontSize: 12.5 }}>
              <thead><tr><th>Service</th><th className="num">Bookings</th><th className="num">Revenue</th><th className="num">Profit</th><th className="num">Cancels</th><th className="num">Share</th></tr></thead>
              <tbody>
                {[
                { svc: "Accommodation", kind: "hotel", bk: 0.52, rev: 0.58, cx: 0.04 },
                { svc: "Car Rental", kind: "rental", bk: 0.20, rev: 0.18, cx: 0.05 },
                { svc: "Transfer", kind: "transfer", bk: 0.14, rev: 0.12, cx: 0.06 },
                { svc: "Airport Lounge", kind: "vip", bk: 0.07, rev: 0.07, cx: 0.08 },
                { svc: "VIP Airport", kind: "vipas", bk: 0.04, rev: 0.03, cx: 0.10 },
                { svc: "Private Tours", kind: "ptour", bk: 0.03, rev: 0.02, cx: 0.11 }].
                map((r) => {
                  const bookings = Math.round(group.usedIn * 142 * r.bk);
                  const rev = Math.round(group.usedIn * 460 * r.rev);
                  return (
                    <tr key={r.svc}>
                      <td><Tag kind={r.kind}>{r.svc}</Tag></td>
                      <td className="num mono">{bookings.toLocaleString()}</td>
                      <td className="num mono">€{rev.toLocaleString()}k</td>
                      <td className="num mono" style={{ color: "var(--success)" }}>€{Math.round(rev * 0.3).toLocaleString()}k</td>
                      <td className="num mono muted">{Math.round(bookings * r.cx)}</td>
                      <td className="num mono">{(r.rev * 100).toFixed(0)}%</td>
                    </tr>);
                })}
              </tbody>
            </table>
          </Card>

          <Card title="Rebookings" sub="Savings generated for this group" flush style={{ marginBottom: 16 }}>
            <div className="grid grid--3" style={{ gap: 12, padding: 14 }}>
              <div><div className="tiny muted">Successful rebooks</div><div className="bold" style={{ fontSize: 18 }}>{group.usedIn * 18}</div></div>
              <div><div className="tiny muted">Money saved (YTD)</div><div className="bold" style={{ fontSize: 18, color: "var(--success)" }}>€{(group.usedIn * 4.2).toFixed(0)}00</div></div>
              <div><div className="tiny muted">Avg saving</div><div className="bold" style={{ fontSize: 18 }}>11.4%</div></div>
            </div>
          </Card>

          <Card title="Rappel agreement" sub="Group-level rebate — same setup as an agency, but split with members">
            <div className="grid grid--4" style={{ gap: 12, marginBottom: 14 }}>
              <div style={{ padding: 14, background: "var(--bg-subtle)", borderRadius: 10 }}>
                <div className="tiny muted">Rappel rate</div>
                <div style={{ fontSize: 20, fontWeight: 700 }}>{group.rappel}%</div>
                <div className="tiny muted">On NET sales</div>
              </div>
              <div style={{ padding: 14, background: "var(--bg-subtle)", borderRadius: 10 }}>
                <div className="tiny muted">Threshold</div>
                <div style={{ fontSize: 20, fontWeight: 700 }}>€{(group.usedIn * 6).toFixed(0)}00k</div>
                <div className="tiny muted">Annual NET target</div>
              </div>
              <div style={{ padding: 14, background: "var(--bg-subtle)", borderRadius: 10 }}>
                <div className="tiny muted">Achieved (YTD)</div>
                <div style={{ fontSize: 20, fontWeight: 700 }}>€{(group.usedIn * 4.6).toFixed(0)}00k <span className="tiny" style={{ color: "var(--indigo)", fontWeight: 600 }}>· 77%</span></div>
                <ProgressBar value={77} color="#635bff" />
                <div className="tiny muted" style={{ marginTop: 4 }}>77% of threshold reached</div>
              </div>
              <div style={{ padding: 14, background: "var(--bg-subtle)", borderRadius: 10 }}>
                <div className="tiny muted">Rappel to be paid</div>
                <div style={{ fontSize: 20, fontWeight: 700, color: "var(--success)" }}>€{(group.usedIn * group.rappel * 4200).toLocaleString()}</div>
                <div className="tiny muted">Accrued · split below</div>
              </div>
            </div>
            <div className="row" style={{ gap: 14 }}>
              <span className="tiny muted">Settlement: quarterly · paid to the group, then divided across member agencies.</span>
              <span className="spacer" />
              <Button kind="secondary" size="sm" icon={<Icon.Edit />} onClick={() => {
                var gid = open && (open.id || open._real && open._real.id);
                if (!gid) { toast({ title: "Open a travel group first", tone: "warning" }); return; }
                var raw = window.prompt("New rappel % for this travel group (0-100)?", String(open.rappel || ""));
                if (raw == null) return;
                var pct = Number(raw);
                if (!isFinite(pct) || pct < 0 || pct > 100) { toast({ title: "Invalid rappel %", tone: "danger" }); return; }
                if (!window.TrekkoAPI || !window.TrekkoAPI.setTravelGroupRappel) { toast({ title: "Endpoint unavailable", tone: "danger" }); return; }
                window.TrekkoAPI.setTravelGroupRappel(gid, pct)
                  .then(function (r) { toast({ title: "Group rappel set to " + r.rappel_percentage + "%", tone: "success" }); })
                  .catch(function (e) { toast({ title: "Set rappel failed", body: String(e && e.message || e), tone: "danger" }); });
              }}>Set rappel</Button>
            </div>
          </Card>

          <div style={{ height: 14 }} />
          <Card title="Rappel split across member agencies" sub="How the group rebate is divided" flush>
            <table className="tbl" style={{ fontSize: 12.5 }}>
              <thead><tr><th>Agency</th><th className="num">NET sales</th><th className="num">Share</th><th className="num">Rappel due</th></tr></thead>
              <tbody>
                {(group.agencies || []).map((name, i) => {
                  const total = group.usedIn * group.rappel * 4200;
                  const share = (group.agencies.length ? 100 / group.agencies.length : 0) + (i === 0 ? 8 : -3);
                  return (
                    <tr key={name}>
                      <td className="bold">{name}</td>
                      <td className="num mono">€{(share / 100 * group.usedIn * 46000).toFixed(0).toLocaleString()}</td>
                      <td className="num mono">{share.toFixed(0)}%</td>
                      <td className="num mono" style={{ color: "var(--success)" }}>€{Math.round(share / 100 * total).toLocaleString()}</td>
                    </tr>);
                })}
              </tbody>
            </table>
          </Card>

          <div style={{ height: 14 }} />
          <Card title="Rappel earnings · 12 months">
            <AreaChart
              height={180}
              data={trend}
              valueFmt={(v) => v + "%"}
              series={[{ key: "rappel", name: "Earned %", color: "#0e7c66" }]} />
            
          </Card>

          <div style={{ height: 14 }} />
          <Card title="Agreement details">
            <dl className="dl">
              <dt>Group code</dt><dd className="mono bold">{group.code}</dd>
              <dt>Type</dt><dd>Volume-based Rappel</dd>
              <dt>Tier structure</dt><dd>0–500k @ {(group.rappel - 1).toFixed(1)}% · 500k–1M @ {group.rappel}% · 1M+ @ {(group.rappel + 1).toFixed(1)}%</dd>
              <dt>Settlement</dt><dd>Quarterly · 30 days after period close</dd>
              <dt>Eligibility</dt><dd>Hotels, Rental Cars, VIP services</dd>
              <dt>Exclusions</dt><dd className="muted">Flights · non-refundable rates</dd>
              <dt>Auto-renewal</dt><dd>Yes — every 12 months</dd>
              <dt>Next review</dt><dd className="mono">Sep 30, 2026</dd>
              <dt>Owner</dt><dd>Hannah Briggs · Finance Analyst</dd>
            </dl>
          </Card>

          <div style={{ height: 14 }} />
          <Card title="Member agencies" sub={`${group.agencies?.length || 0} agencies in this group`} flush>
            <table className="tbl" style={{ fontSize: 12.5 }}>
              <thead><tr><th>Agency</th><th>Country</th><th className="num">Bookings (YTD)</th><th className="num">Sales (YTD)</th><th className="num">Rappel earned</th></tr></thead>
              <tbody>
                {(group.agencies || []).map((name) => {
                  const a = agencies.find((x) => x.name === name) || { country: "—", bookings: 0, sales: 0 };
                  const earned = Math.round((a.sales || 0) * group.rappel / 100);
                  return (
                    <tr key={name}>
                      <td className="bold">{name}</td>
                      <td className="muted">{a.country}</td>
                      <td className="num mono">{a.bookings}</td>
                      <td className="num mono">€{(a.sales || 0).toLocaleString()}</td>
                      <td className="num mono bold" style={{ color: "var(--success)" }}>€{earned.toLocaleString()}</td>
                    </tr>);

                })}
              </tbody>
            </table>
          </Card>

          <div style={{ height: 14 }} />
          <Card title="Timeline" flush>
            <ul style={{ margin: 0, padding: 0, listStyle: "none", fontSize: 13 }}>
              {[
              { ic: "Refresh", when: "2 hr ago", what: "Q2 Rappel calculation completed — €18,420 earned", tone: "success" },
              { ic: "Edit", when: "2 weeks ago", what: "Agreement amended — tier 2 raised from 4.5% to 4.8%", tone: "info" },
              { ic: "Plus", when: "1 month ago", what: "Wired World added to group", tone: "indigo" },
              { ic: "Doc", when: "Apr 1, 2026", what: "Q1 settlement issued — €14,200 paid out", tone: "success" },
              { ic: "Check", when: "Jan 12, 2026", what: "Annual agreement signed for 2026", tone: "success" }].
              map((e, i) => {
                const Ic = Icon[e.ic];
                return (
                  <li key={i} className="row" style={{ gap: 12, padding: "12px 18px", borderBottom: i < 4 ? "1px solid var(--border-hairline)" : "0" }}>
                    <span style={{
                      width: 26, height: 26, borderRadius: 999, flexShrink: 0,
                      display: "grid", placeItems: "center",
                      background: `var(--${e.tone}-bg)`,
                      color: `var(--${e.tone === "indigo" ? "indigo" : e.tone})`
                    }}><Ic size={13} /></span>
                    <div style={{ flex: 1 }}>
                      <div style={{ fontSize: 13 }}>{e.what}</div>
                      <div className="tiny muted">{e.when}</div>
                    </div>
                  </li>);

              })}
            </ul>
          </Card>
        </div>
        <div className="modal__foot">
          <Button kind="ghost" onClick={onClose}>Close</Button>
          <span className="spacer" />
          <Button kind="secondary" icon={<Icon.Doc />}>Download agreement</Button>
          <Button kind="primary" icon={<Icon.Edit />}>Edit group</Button>
        </div>
      </div>
    </>);

}

function TGFormModal({ open, onClose, group }) {
  const [agencies, setAgencies] = useState_ex((window.MOCK && window.MOCK.TRAVEL_AGENCIES) || []);
  useEffect_ex(() => {
    if (!open || !window.TrekkoAPI) return;
    window.TrekkoAPI.getAgencies().then((rows) => { if (rows && rows.length) setAgencies(rows); });
  }, [open]);
  if (!open) return null;
  return (
    <Modal open onClose={onClose} title={group ? `Edit ${group.name}` : "Add travel group"} size="lg"
    footer={<><Button kind="secondary" onClick={onClose}>Cancel</Button>
              <Button kind="primary" icon={<Icon.Check />} onClick={() => {onClose();toast({ title: group ? "Group updated" : "Group created", tone: "success" });}}>{group ? "Save changes" : "Create group"}</Button></>}>
      <div className="grid grid--2" style={{ gap: 14 }}>
        <Field label="Group code"><input className="input" defaultValue={group?.code || ""} placeholder="e.g. OPT-ES" /></Field>
        <Field label="Rappel percentage (%)"><input className="input" type="number" step="0.1" defaultValue={group?.rappel ?? 5.0} /></Field>
        <Field label="Settlement period"><select className="select"><option>Monthly</option><option selected>Quarterly</option><option>Half-yearly</option><option>Yearly</option></select></Field>
        <Field label="Eligibility"><select className="select" multiple style={{ height: 70 }}><option selected>Hotels</option><option selected>Rental Cars</option><option>Transfer</option><option selected>VIP services</option><option>Private Tours</option><option>Flight</option></select></Field>
        <div style={{ gridColumn: "1 / -1" }}>
          <Field label="Travel group name"><input className="input" defaultValue={group?.name || ""} placeholder="OptiTron Iberia" /></Field>
        </div>
        <div style={{ gridColumn: "1 / -1" }}>
          <Field label="Description"><textarea className="textarea" defaultValue={group?.description || ""} placeholder="Short description for this group…" /></Field>
        </div>
        <div style={{ gridColumn: "1 / -1" }}>
          <Field label="Apply to agencies">
            <select multiple className="select" style={{ height: 120 }} defaultValue={group?.agencies || []}>
              {agencies.map((a) => <option key={a.id}>{a.name}</option>)}
            </select>
          </Field>
        </div>
      </div>
    </Modal>);

}

function TGDeleteModal({ group, onClose }) {
  if (!group) return null;
  return (
    <Modal open onClose={onClose} title="Delete travel group"
    footer={<><Button kind="secondary" onClick={onClose}>Cancel</Button>
              <Button kind="danger" icon={<Icon.Trash />} onClick={() => {onClose();toast({ title: "Group deleted", body: `${group.name} removed.`, tone: "danger" });}}>Delete group</Button></>}>
      <div className="row" style={{ gap: 10, marginBottom: 14, background: "var(--danger-bg)", padding: "10px 12px", borderRadius: 8 }}>
        <Icon.Warning stroke="var(--danger)" />
        <div style={{ fontSize: 13, color: "var(--danger)" }}>Deleting <b>{group.name}</b> will remove the Rappel agreement from <b>{group.usedIn}</b> {group.usedIn === 1 ? "agency" : "agencies"}. Past settlements stay untouched.</div>
      </div>
      <Field label="Type the group code to confirm"><input className="input" placeholder={group.code} /></Field>
    </Modal>);

}

// ============================================================
// PAYMENT MANAGEMENT — Enhanced (Bookings + Wallets + Topups + Payouts + Reconciliation + Refunds)
// ============================================================
function PagePaymentsEnhanced({ onOpenDetail }) {
  const [tab, setTab] = useState_ex("bookings");
  return (
    <div data-comment-anchor="5e6bb170bd-div-258-5">
      <div className="page-head">
        <div>
          <h1 className="page-head__title">Payment Management</h1>
          <div className="page-head__sub" data-comment-anchor="2f9becad51-div-262-11">Receivables from agencies, wallets, refunds and reconciliation.</div>
        </div>
        <div className="page-head__actions">
          <PeriodPicker value="month" onChange={() => {}} />
          <Button kind="secondary" icon={<Icon.Download />}>Export</Button>
        </div>
      </div>

      <Tabs active={tab} onChange={setTab} tabs={[
      { id: "bookings", label: "Receivables (bookings)" },
      { id: "wallets", label: "Virtual wallets" },
      { id: "topups", label: "Recent transactions" },
      { id: "transfers", label: "Bank transfers received" },
      { id: "refunds", label: "Refunds (auto)", count: 6 },
      { id: "recon", label: "Reconciliation", count: 12 },
      { id: "invoices", label: "Invoices" }]
      } />

      {tab === "bookings" && <window.PageBookings onOpenDetail={onOpenDetail} />}
      {tab === "wallets" && <window.WalletsView />}
      {tab === "topups" && <window.TopUpsView />}
      {tab === "transfers" && <BankTransfersView />}
      {tab === "refunds" && <RefundsView />}
      {tab === "recon" && <ReconciliationView />}
      {tab === "invoices" && <InvoicesView />}
    </div>);

}

// -----------------------------------------------------------
// Bank transfers received — enter & assign to agency
// -----------------------------------------------------------
function BankTransfersView() {
  const [addOpen, setAddOpen] = useState_ex(false);
  const [assignTx, setAssignTx] = useState_ex(null);
  const [rows, setRows] = useState_ex([
  { id: "BT-2042", agency: "Optitron Travel Solutions", amount: 18400, date: "2026-05-28", invoice: "INV-2026-0421", ref: "TRF-99812", market: "Iberia", status: "Assigned" },
  { id: "BT-2041", agency: "SunTours España", amount: 12200, date: "2026-05-27", invoice: "INV-2026-0418", ref: "TRF-99788", market: "Iberia", status: "Assigned" },
  { id: "BT-2040", agency: "—", amount: 8600, date: "2026-05-27", invoice: "—", ref: "TRF-99771", market: "—", status: "Unassigned" },
  { id: "BT-2039", agency: "Global Ventures Ltd", amount: 24800, date: "2026-05-26", invoice: "INV-2026-0415", ref: "TRF-99740", market: "UK", status: "Assigned" },
  { id: "BT-2038", agency: "—", amount: 4200, date: "2026-05-26", invoice: "—", ref: "TRF-99722", market: "—", status: "Unassigned" }]
  );
  return (
    <>
      <div className="grid grid--4" style={{ marginBottom: 18 }}>
        <Metric accent label="Received this month" value="€284k" delta="+12% MoM · +22% YoY" deltaDir="up" />
        <Metric label="Assigned" value="€271k" hint="95.4% of total" />
        <Metric label="Unassigned" value="€12.8k" delta="2 transfers" deltaDir="down" hint="Action required" />
        <Metric label="Avg transfer" value="€13.6k" hint="Last 30 days" />
      </div>
      <div className="filter-bar" data-comment-anchor="0f6c73b207-div-311-7">
        <input className="input input--search" placeholder="Search by agency, ref or invoice…" style={{ width: 320 }} />
        <select className="select"><option>All markets</option><option>Iberia</option><option>DACH</option><option>UK</option><option>France</option><option>Nordics</option></select>
        <select className="select"><option>All statuses</option><option>Assigned</option><option>Unassigned</option></select>
        <span className="spacer" />
        <Button kind="primary" icon={<Icon.Plus />} onClick={() => setAddOpen(true)}>Enter bank transfer</Button>
      </div>
      <div className="tbl-wrap tbl-wrap--linked">
        <table className="tbl">
          <thead>
            <tr><th>Transfer ID</th><th>Bank reference</th><th>Agency</th><th>Market</th><th>Invoice</th><th className="num">Amount</th><th>Date</th><th>Status</th><th className="col-actions"></th></tr>
          </thead>
          <tbody>
            {rows.map((t) =>
            <tr key={t.id}>
                <td className="mono">{t.id}</td>
                <td className="mono muted">{t.ref}</td>
                <td className="bold">{t.agency}</td>
                <td className="muted">{t.market}</td>
                <td className="mono">{t.invoice}</td>
                <td className="num mono bold">€{t.amount.toLocaleString()}</td>
                <td className="mono">{t.date}</td>
                <td>{t.status === "Assigned" ? <Badge tone="success">Assigned</Badge> : <Badge tone="warning">Unassigned</Badge>}</td>
                <td className="col-actions">
                  {t.status === "Unassigned" ?
                <Button kind="primary" size="sm" onClick={() => setAssignTx(t)}>Assign</Button> :
                <Button kind="secondary" size="sm" onClick={() => {
                  window.TrekkoAPI.viewTransfer(t.id)
                    .then(function (r) { toast({ title: t.id + " · " + t.agency, body: (r && r.note) || ("€" + t.amount.toLocaleString()), tone: "info" }); })
                    .catch(function (e) { toast({ title: "View failed", body: String(e && e.message || e), tone: "danger" }); });
                }}>View</Button>}
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
      <EnterTransferModal open={addOpen} onClose={() => setAddOpen(false)} />
      <AssignTransferModal tx={assignTx} onClose={() => setAssignTx(null)} />
    </>);

}

function AssignTransferModal({ tx, onClose }) {
  if (!tx) return null;
  return (
    <Modal open onClose={onClose} title={`Assign transfer · ${tx.id}`} size="lg"
    footer={<><Button kind="secondary" onClick={onClose}>Cancel</Button>
              <Button kind="primary" icon={<Icon.Check />} onClick={() => {onClose();toast({ title: "Transfer assigned", body: tx.id + " allocated.", tone: "success" });}}>Assign funds</Button></>}>
      <div className="row" style={{ gap: 8, marginBottom: 14, padding: "10px 12px", background: "var(--bg-subtle)", borderRadius: 8 }}>
        <Icon.Building stroke="var(--ink-3)" />
        <div><div className="bold">€{tx.amount.toLocaleString()}</div><div className="tiny muted">{tx.ref} · received {tx.date}</div></div>
      </div>
      <div className="grid grid--2" style={{ gap: 14 }}>
        <div style={{ gridColumn: "1 / -1" }}><Field label="Travel agency"><AgencySearchSelect /></Field></div>
        <div style={{ gridColumn: "1 / -1" }}>
          <Field label="Allocate to" hint="Where these funds should be applied.">
            <select className="select">
              <option value="wallet">Virtual wallet (prepaid balance)</option>
              <option value="deposit">Floating deposit (credit agencies)</option>
              <option value="repayment">Credit repayment (settle open invoices)</option>
              <option value="mixed">Split — repay credit, remainder to wallet</option>
            </select>
          </Field>
        </div>
        <Field label="Apply to invoice(s)" hint="Multi-select for credit repayment.">
          <select className="select" multiple style={{ height: 90 }}>
            <option>INV-2026-0421 · €2,180</option>
            <option>INV-2026-0419 · €1,420</option>
            <option>INV-2026-0410 · €580</option>
            <option>INV-2026-0403 · €3,420</option>
          </select>
        </Field>
        <Field label="Amount to allocate (€)"><input className="input" type="number" defaultValue={tx.amount} /></Field>
        <Field label="Value date"><input className="input" type="date" /></Field>
        <Field label="Reference"><input className="input" defaultValue={tx.ref} /></Field>
        <div style={{ gridColumn: "1 / -1" }}><Field label="Notes"><textarea className="textarea" placeholder="Optional notes…" /></Field></div>
      </div>
    </Modal>);
}

function AgencySearchSelect() {
  const { useState, useEffect } = React;
  const [q, setQ] = useState("");
  const [sel, setSel] = useState("");
  const [open, setOpen] = useState(false);
  const [agencies, setAgencies] = useState((window.MOCK && window.MOCK.TRAVEL_AGENCIES) || []);
  useEffect(() => {
    if (!window.TrekkoAPI) return;
    window.TrekkoAPI.getAgencies().then((rows) => { if (rows && rows.length) setAgencies(rows); });
  }, []);
  const matches = agencies.filter((a) => a.name.toLowerCase().includes(q.toLowerCase()));
  return (
    <div style={{ position: "relative" }}>
      <input className="input input--search" placeholder="Search agency…" value={sel || q}
      onChange={(e) => {setQ(e.target.value);setSel("");setOpen(true);}}
      onFocus={() => setOpen(true)}
      onBlur={() => setTimeout(() => setOpen(false), 150)} />
      {open && matches.length > 0 &&
      <div style={{ position: "absolute", top: 38, left: 0, right: 0, zIndex: 50, background: "#fff", border: "1px solid var(--border)", borderRadius: 8, boxShadow: "var(--shadow-md)", maxHeight: 200, overflowY: "auto" }}>
        {matches.map((a) =>
        <div key={a.id} onMouseDown={() => {setSel(a.name);setQ("");setOpen(false);}}
        style={{ padding: "8px 12px", cursor: "pointer", fontSize: 13 }}
        onMouseEnter={(e) => e.currentTarget.style.background = "var(--bg-subtle)"}
        onMouseLeave={(e) => e.currentTarget.style.background = "#fff"}>
          {a.name} <span className="tiny muted">· {a.id}</span>
        </div>)}
      </div>}
    </div>);
}

function EnterTransferModal({ open, onClose }) {
  if (!open) return null;
  return (
    <Modal open onClose={onClose} title="Enter bank transfer received" size="lg"
    footer={<><Button kind="secondary" onClick={onClose}>Cancel</Button>
              <Button kind="primary" icon={<Icon.Check />} onClick={() => {onClose();toast({ title: "Bank transfer recorded", body: "Assigned to agency.", tone: "success" });}}>Save & assign</Button></>}>
      <div className="grid grid--2" style={{ gap: 14 }}>
        <Field label="Agency"><AgencySearchSelect /></Field>
        <Field label="Amount (€)"><input className="input" type="number" placeholder="0.00" /></Field>
        <div style={{ gridColumn: "1 / -1" }}>
          <Field label="Allocate to" hint="Where these funds should be applied for the agency.">
            <select className="select">
              <option value="wallet">Virtual wallet (prepaid balance)</option>
              <option value="deposit">Floating deposit (credit agencies)</option>
              <option value="repayment">Credit repayment (settle open invoices)</option>
              <option value="mixed">Split — repay credit, remainder to wallet</option>
            </select>
          </Field>
        </div>
        <Field label="Transfer date"><input className="input" type="date" /></Field>
        <Field label="Value date"><input className="input" type="date" /></Field>
        <Field label="Bank reference"><input className="input" placeholder="TRF-00000" /></Field>
        <Field label="Invoice / statement no." hint="Required for credit repayment."><input className="input" placeholder="INV-2026-0000" /></Field>
        <Field label="Currency"><select className="select"><option>EUR</option><option>USD</option><option>GBP</option></select></Field>
        <Field label="Bank account"><select className="select"><option>BBVA · ES91 ···· 1332</option><option>Santander · ES44 ···· 8821</option></select></Field>
        <div style={{ gridColumn: "1 / -1" }}>
          <Field label="Notes"><textarea className="textarea" placeholder="Optional notes about this transfer…" /></Field>
        </div>
      </div>
    </Modal>);

}

// -----------------------------------------------------------
// Payouts to vendors
// -----------------------------------------------------------
function PayoutsView() {
  const [detail, setDetail] = useState_ex(null);
  const ROWS = [
  { id: "PO-7821", vendor: "Marriott International", method: "SEPA", amount: 28400, fees: 12, period: "May 1 — May 15", status: "Scheduled", date: "2026-05-20", bookings: 142 },
  { id: "PO-7820", vendor: "Hilton Worldwide", method: "SEPA", amount: 19800, fees: 12, period: "May 1 — May 15", status: "Scheduled", date: "2026-05-20", bookings: 98 },
  { id: "PO-7819", vendor: "Sixt Rent a Car", method: "SEPA", amount: 12400, fees: 8, period: "May 1 — May 15", status: "In review", date: "—", bookings: 312 },
  { id: "PO-7818", vendor: "AC Hotels Group", method: "SEPA", amount: 9820, fees: 12, period: "Apr 16 — Apr 30", status: "Paid", date: "2026-05-05", bookings: 64 },
  { id: "PO-7817", vendor: "Europcar Mobility Group", method: "SEPA", amount: 21200, fees: 8, period: "Apr 16 — Apr 30", status: "Paid", date: "2026-05-05", bookings: 482 },
  { id: "PO-7816", vendor: "Olympia Tours", method: "Wire", amount: 4180, fees: 22, period: "Apr 16 — Apr 30", status: "Failed", date: "2026-05-05", bookings: 22 },
  { id: "PO-7815", vendor: "Costa Cruises", method: "SEPA", amount: 12800, fees: 12, period: "Apr 16 — Apr 30", status: "Paid", date: "2026-05-05", bookings: 18 },
  { id: "PO-7814", vendor: "Eurostar Group", method: "SEPA", amount: 6400, fees: 12, period: "Apr 16 — Apr 30", status: "Paid", date: "2026-05-05", bookings: 84 }];

  return (
    <>
      <div className="grid grid--4" style={{ marginBottom: 18 }}>
        <Metric accent label="Owed to vendors" value="€89,420" delta="+12% MoM" deltaDir="up" hint="Next batch May 20" />
        <Metric label="Paid out (YTD)" value="€1.42M" delta="+22% YoY" deltaDir="up" />
        <Metric label="Pending review" value="3" hint="€16,580 awaiting approval" />
        <Metric label="Failed payouts" value="1" delta="−2 vs LM" deltaDir="down" hint="Auto-retry in 24 h" />
      </div>

      <div className="filter-bar">
        <input className="input input--search" placeholder="Search by vendor or payout ID…" style={{ width: 320 }} />
        <select className="select"><option>All statuses</option><option>Scheduled</option><option>In review</option><option>Paid</option><option>Failed</option></select>
        <select className="select"><option>All methods</option><option>SEPA</option><option>Wire</option><option>Card</option></select>
        <select className="select"><option>This period</option><option>Last period</option><option>Last 90 days</option></select>
        <span className="spacer" />
        <Button kind="secondary" icon={<Icon.Download />}>Export</Button>
        <Button kind="primary" icon={<Icon.Send />} onClick={() => {
          if (!window.confirm("Queue a batch payout for all scheduled vendor payouts?")) return;
          window.TrekkoAPI.runBatchPayout({ vendor_ids: [], payout_ids: [] })
            .then(function () { toast({ title: "Batch payout queued", body: "Backend will process queued payouts in the next worker pass.", tone: "success" }); })
            .catch(function (e) { toast({ title: "Batch payout failed", body: String(e && e.message || e), tone: "danger" }); });
        }}>Run batch payout</Button>
      </div>

      <div className="tbl-wrap tbl-wrap--linked">
        <table className="tbl">
          <thead>
            <tr><th>Payout</th><th>Vendor</th><th>Period</th><th className="num">Bookings</th><th>Method</th><th className="num">Amount</th><th className="num">Fees</th><th>Date</th><th>Status</th><th className="col-actions"></th></tr>
          </thead>
          <tbody>
            {ROWS.map((r) =>
            <tr key={r.id}>
                <td className="mono"><a href="#" onClick={(e) => {e.preventDefault();setDetail(r);}}>{r.id}</a></td>
                <td className="bold">{r.vendor}</td>
                <td className="mono muted">{r.period}</td>
                <td className="num mono">{r.bookings}</td>
                <td><span className="row" style={{ gap: 6 }}><Icon.Building size={12} /> {r.method}</span></td>
                <td className="num mono bold">€{r.amount.toLocaleString()}</td>
                <td className="num mono muted">€{r.fees}</td>
                <td className="mono">{r.date}</td>
                <td>{r.status === "Paid" ? <Badge tone="success">Paid</Badge> :
                r.status === "Scheduled" ? <Badge tone="info">Scheduled</Badge> :
                r.status === "In review" ? <Badge tone="warning">In review</Badge> :
                <Badge tone="danger">Failed</Badge>}</td>
                <td className="col-actions"><Button kind="secondary" size="sm" onClick={() => setDetail(r)}>View</Button></td>
              </tr>
            )}
          </tbody>
        </table>
      </div>

      {detail &&
      <Modal open onClose={() => setDetail(null)} title={`Payout ${detail.id}`} size="lg"
      footer={<><Button kind="secondary" onClick={() => setDetail(null)}>Close</Button>
                   {detail.status === "Failed" && <Button kind="primary" icon={<Icon.Refresh />} onClick={() => {setDetail(null);toast({ title: "Payout retried", tone: "success" });}}>Retry</Button>}
                   {detail.status === "In review" && <Button kind="success" icon={<Icon.Check />} onClick={() => {setDetail(null);toast({ title: "Payout approved", tone: "success" });}}>Approve</Button>}</>}>
          <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 16 }}>
            <div>
              <div className="muted tiny">Amount</div>
              <div style={{ fontSize: 28, fontWeight: 700, letterSpacing: "-0.02em" }}>€{detail.amount.toLocaleString()}</div>
              <div className="muted tiny">Net €{(detail.amount - detail.fees).toLocaleString()} after €{detail.fees} fee</div>
              <div style={{ height: 14 }} />
              <div className="muted tiny">Status</div>
              <div><Badge tone={detail.status === "Paid" ? "success" : detail.status === "Scheduled" ? "info" : detail.status === "In review" ? "warning" : "danger"}>{detail.status}</Badge></div>
            </div>
            <div>
              <dl className="dl">
                <dt>Vendor</dt><dd className="bold">{detail.vendor}</dd>
                <dt>Period</dt><dd className="mono">{detail.period}</dd>
                <dt>Bookings</dt><dd>{detail.bookings} included</dd>
                <dt>Method</dt><dd>{detail.method}</dd>
                <dt>Beneficiary IBAN</dt><dd className="mono">ES91 2100 0418 4502 0005 1332</dd>
                <dt>Reference</dt><dd className="mono">TREK-{detail.id}</dd>
              </dl>
            </div>
          </div>
        </Modal>
      }
    </>);

}

// -----------------------------------------------------------
// Refunds queue
// -----------------------------------------------------------
function RefundsView() {
  const ROWS = [
  { id: "RF-3401", booking: "BK-12482", agency: "OptiTron Tech", reason: "Customer cancellation", amount: 940, status: "Auto-processed", raised: "2 hr ago", who: "System" },
  { id: "RF-3400", booking: "BK-12479", agency: "Wired World", reason: "Vendor unavailable", amount: 612, status: "Auto-processed", raised: "Yesterday", who: "System" },
  { id: "RF-3399", booking: "BK-12476", agency: "Pacific Horizons", reason: "Duplicate booking", amount: 480, status: "Auto-processed", raised: "Today 11:14", who: "System" },
  { id: "RF-3398", booking: "BK-12471", agency: "Industrial Dynamics", reason: "Price match", amount: 32, status: "Processing", raised: "Today 09:42", who: "System" },
  { id: "RF-3397", booking: "BK-12465", agency: "Aurora Routes", reason: "Force majeure", amount: 1310, status: "Manual review", raised: "3 days ago", who: "Hannah Briggs" },
  { id: "RF-3396", booking: "BK-12459", agency: "Paramount Products", reason: "Customer request", amount: 200, status: "Auto-processed", raised: "5 days ago", who: "System" }];

  return (
    <>
      <div className="row" style={{ gap: 10, marginBottom: 16, background: "var(--info-bg)", padding: "10px 12px", borderRadius: 8, color: "var(--info)" }}>
        <Icon.Refresh stroke="currentColor" />
        <div style={{ fontSize: 13 }}>Refunds are <b>processed automatically</b> based on the cancellation policy of each booking. Only edge cases (force majeure, disputes) are escalated to manual review.</div>
      </div>
      <div className="grid grid--4" style={{ marginBottom: 18 }}>
        <Metric accent label="Auto-processed (month)" value="142" delta="+18% MoM · +24% YoY" deltaDir="up" hint="€84,200 refunded" />
        <Metric label="Processing now" value="3" hint="€1,420 in flight" />
        <Metric label="Manual review" value="1" delta="Force majeure" deltaDir="down" />
        <Metric label="Refund rate" value="2.4%" delta="−0.3 pt MoM" deltaDir="down" hint="Of total bookings" />
      </div>

      <div className="filter-bar">
        <input className="input input--search" placeholder="Search by refund or booking ID…" style={{ width: 320 }} />
        <select className="select"><option>All statuses</option><option>Auto-processed</option><option>Processing</option><option>Manual review</option></select>
        <select className="select"><option>All markets</option><option>Iberia</option><option>DACH</option><option>UK</option><option>France</option><option>Nordics</option></select>
        <span className="spacer" />
        <Button kind="secondary" icon={<Icon.Download />}>Export</Button>
      </div>

      <div className="tbl-wrap tbl-wrap--linked">
        <table className="tbl">
          <thead>
            <tr><th>Refund</th><th>Booking</th><th>Agency</th><th>Reason</th><th className="num">Amount</th><th>Processed</th><th>By</th><th>Status</th><th className="col-actions"></th></tr>
          </thead>
          <tbody>
            {ROWS.map((r) =>
            <tr key={r.id}>
                <td className="mono">{r.id}</td>
                <td className="mono">{r.booking}</td>
                <td className="bold">{r.agency}</td>
                <td className="muted">{r.reason}</td>
                <td className="num mono bold">€{r.amount.toLocaleString()}</td>
                <td className="mono muted">{r.raised}</td>
                <td><span className="user-cell"><Avatar name={r.who} size="sm" />{r.who}</span></td>
                <td>{r.status === "Auto-processed" ? <Badge tone="success">Auto-processed</Badge> :
                r.status === "Processing" ? <Badge tone="info">Processing</Badge> :
                <Badge tone="warning">Manual review</Badge>}</td>
                <td className="col-actions">
                  {r.status === "Manual review" ?
                <Button kind="success" size="sm" onClick={() => {
                  if (!window.confirm("Approve refund " + r.id + " of €" + r.amount.toLocaleString() + "?\\n\\nIf a booking_number is attached, this triggers a REAL Stripe refund. Otherwise it audit-logs the intent.")) return;
                  if (!window.TrekkoAPI || !window.TrekkoAPI.approveRefund) { toast({ title: "Endpoint unavailable", tone: "danger" }); return; }
                  window.TrekkoAPI.approveRefund({ refund_id: r.id, booking_number: r.booking_number || null, amount: r.amount, reason: "Approved via CRM" })
                    .then(function (resp) {
                      if (resp && resp.audit_only) {
                        toast({ title: "Refund audit-logged", body: "No payment_intent to send to Stripe — handled manually.", tone: "info" });
                      } else {
                        toast({ title: "Stripe refund " + (resp && resp.status), body: "€" + r.amount.toLocaleString() + " on " + r.id, tone: "success" });
                      }
                    })
                    .catch(function (e) { toast({ title: "Refund approval failed", body: String(e && e.message || e), tone: "danger" }); });
                }}>Approve</Button> :
                <Button kind="secondary" size="sm" onClick={() => toast({ title: "Refund " + r.id, body: r.agency + " · €" + r.amount.toLocaleString(), tone: "info" })}>View</Button>}
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
    </>);

}

// -----------------------------------------------------------
// Reconciliation
// -----------------------------------------------------------
function ReconciliationView() {
  const [tab, setTab] = useState_ex("unmatched");
  return (
    <>
      <div className="grid grid--4" style={{ marginBottom: 18 }}>
        <Metric accent label="Reconciliation rate" value="98.4%" delta="+0.2 pt" deltaDir="up" hint="Last 30 days" />
        <Metric label="Unmatched payments" value="12" hint="€8,240 to reconcile" />
        <Metric label="Auto-matched today" value="284" delta="100% accuracy" deltaDir="up" />
        <Metric label="Open disputes" value="3" hint="€1,840 in dispute" />
      </div>

      <Segmented value={tab} onChange={setTab} options={[
      { value: "unmatched", label: `Unmatched (12)` },
      { value: "matched", label: "Matched today" },
      { value: "disputes", label: "Disputes" }]
      } />

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

      {tab === "unmatched" &&
      <Card title="Unmatched incoming payments" sub="Click a row to manually link to a booking" flush>
          <table className="tbl">
            <thead><tr><th>Received</th><th>From</th><th className="num">Amount</th><th>Reference</th><th>Method</th><th>Suggested match</th><th className="col-actions"></th></tr></thead>
            <tbody>
              {[
            { d: "Today 10:14", from: "OptiTron Tech", amt: 4500, ref: "trf_44218", m: "SEPA", sug: "INV-2026-0421 (€2,180 part)" },
            { d: "Today 09:42", from: "Industrial Dynamics", amt: 12000, ref: "TRF8821 batch", m: "SEPA", sug: "INV-2026-0418 + INV-2026-0419" },
            { d: "Today 08:01", from: "Pacific Horizons", amt: 818, ref: "—", m: "Wire", sug: "No suggestion · review manually" },
            { d: "Yesterday 17:22", from: "Anonymous (FR)", amt: 1480, ref: "Ref FR-9981", m: "SEPA", sug: "No suggestion · check sender" },
            { d: "Yesterday 11:08", from: "Wired World", amt: 528, ref: "BK-12479", m: "Card", sug: "Booking BK-12479 (perfect)" }].
            map((r, i) =>
            <tr key={i}>
                  <td className="mono muted">{r.d}</td>
                  <td className="bold">{r.from}</td>
                  <td className="num mono bold">€{r.amt.toLocaleString()}</td>
                  <td className="mono muted">{r.ref}</td>
                  <td>{r.m}</td>
                  <td>{r.sug.includes("perfect") ? <Badge tone="success">{r.sug}</Badge> : r.sug.includes("No suggestion") ? <Badge tone="warning">{r.sug}</Badge> : <Badge tone="info">{r.sug}</Badge>}</td>
                  <td className="col-actions">
                    <div className="row" style={{ gap: 4, justifyContent: "flex-end" }}>
                      {r.sug.includes("perfect") && <Button kind="success" size="sm" onClick={() => {
                        window.TrekkoAPI.applyTreasuryMatch(r.ref || r.d, null, null, "perfect-match auto")
                          .then(function () { toast({ title: "Match applied", body: r.ref || r.d, tone: "success" }); })
                          .catch(function (e) { toast({ title: "Match failed", body: String(e && e.message || e), tone: "danger" }); });
                      }}>Apply match</Button>}
                      <Button kind="secondary" size="sm" onClick={() => {
                        var bid = window.prompt("Booking ID this payment matches?");
                        if (!bid) return;
                        window.TrekkoAPI.applyTreasuryMatch(r.ref || r.d, Number(bid), null, "manual match via CRM")
                          .then(function () { toast({ title: "Match applied", tone: "success" }); })
                          .catch(function (e) { toast({ title: "Match failed", body: String(e && e.message || e), tone: "danger" }); });
                      }}>Match manually</Button>
                    </div>
                  </td>
                </tr>
            )}
            </tbody>
          </table>
        </Card>
      }

      {tab === "matched" &&
      <Card title="Auto-matched today" flush>
          <table className="tbl">
            <thead><tr><th>Matched</th><th>From</th><th className="num">Amount</th><th>Booking / Invoice</th><th>Confidence</th><th>Status</th></tr></thead>
            <tbody>
              {[
            { d: "10:18", from: "AC Hotels Group", amt: 9820, link: "PO-7818", c: 100, s: "Reconciled" },
            { d: "10:11", from: "OptiTron Tech", amt: 2180, link: "INV-2026-0421", c: 100, s: "Reconciled" },
            { d: "09:58", from: "Northwind Travel", amt: 1820, link: "BK-12481", c: 98, s: "Reconciled" },
            { d: "09:42", from: "Hertz", amt: 4180, link: "PO-7816", c: 96, s: "Reconciled" },
            { d: "09:14", from: "Paramount Products", amt: 2800, link: "INV-2026-0418", c: 100, s: "Reconciled" }].
            map((r, i) =>
            <tr key={i}>
                  <td className="mono muted">{r.d}</td>
                  <td className="bold">{r.from}</td>
                  <td className="num mono bold">€{r.amt.toLocaleString()}</td>
                  <td className="mono">{r.link}</td>
                  <td className="num mono">{r.c}%</td>
                  <td><Badge tone="success">{r.s}</Badge></td>
                </tr>
            )}
            </tbody>
          </table>
        </Card>
      }

      {tab === "disputes" &&
      <Card title="Open disputes" flush>
          <table className="tbl">
            <thead><tr><th>Dispute</th><th>Counterparty</th><th>Type</th><th className="num">Amount</th><th>Opened</th><th>Status</th><th className="col-actions"></th></tr></thead>
            <tbody>
              <tr><td className="mono">DI-118</td><td className="bold">Marriott Marbella</td><td>Vendor invoice mismatch</td><td className="num mono">€420</td><td className="mono">3 days ago</td><td><Badge tone="warning">Under review</Badge></td><td className="col-actions"><Button kind="secondary" size="sm">Open</Button></td></tr>
              <tr><td className="mono">DI-117</td><td className="bold">Sixt Rent a Car</td><td>Refund not received</td><td className="num mono">€820</td><td className="mono">1 week ago</td><td><Badge tone="warning">Awaiting bank</Badge></td><td className="col-actions"><Button kind="secondary" size="sm">Open</Button></td></tr>
              <tr><td className="mono">DI-116</td><td className="bold">Costa Cruises</td><td>Currency conversion</td><td className="num mono">€600</td><td className="mono">2 weeks ago</td><td><Badge tone="danger">Escalated</Badge></td><td className="col-actions"><Button kind="secondary" size="sm">Open</Button></td></tr>
            </tbody>
          </table>
        </Card>
      }
    </>);

}

// -----------------------------------------------------------
// Invoices
// -----------------------------------------------------------
function InvoicesView() {
  const [docType, setDocType] = useState_ex("all");
  const FALLBACK_ROWS = [
  { id: "INV-2026-0421", agency: "OptiTron Tech", type: "Invoice", trigger: "Checked-in", issued: "May 1", due: "May 14", bookings: 18, total: 10188, status: "Sent" },
  { id: "PRO-2026-0188", agency: "Paramount Products", type: "Proforma", trigger: "Refundable", issued: "May 1", due: "-", bookings: 22, total: 13818, status: "Proforma" },
  { id: "INV-2026-0419", agency: "OptiTron Tech", type: "Invoice", trigger: "Non-refundable", issued: "Apr 27", due: "May 10", bookings: 12, total: 5832, status: "Overdue" }];
  const [ROWS, setROWS] = useState_ex(FALLBACK_ROWS);
  useEffect_ex(() => {
    if (!window.TrekkoAPI) return;
    window.TrekkoAPI.getInvoices().then((data) => { if (data && data.length) setROWS(data); });
  }, []);
  const totals = React.useMemo(() => {
    const invoiced = ROWS.filter((r) => r.type === "Invoice").reduce((s, r) => s + (Number(r.total) || 0), 0);
    const proforma = ROWS.filter((r) => r.type === "Proforma").reduce((s, r) => s + (Number(r.total) || 0), 0);
    const overdue = ROWS.filter((r) => r.status === "Overdue").reduce((s, r) => s + (Number(r.total) || 0), 0);
    const paid = ROWS.filter((r) => r.status === "Paid").reduce((s, r) => s + (Number(r.total) || 0), 0);
    return { invoiced, proforma, overdue, paid };
  }, [ROWS]);

  const filtered = ROWS.filter((r) => docType === "all" || docType === "invoice" && r.type === "Invoice" || docType === "proforma" && r.type === "Proforma");
  return (
    <>
      <div className="row" style={{ gap: 10, marginBottom: 16, background: "var(--info-bg)", padding: "10px 12px", borderRadius: 8, color: "var(--info)" }}>
        <Icon.Info stroke="currentColor" />
        <div style={{ fontSize: 13 }}>A final <b>Invoice</b> is issued automatically once a booking is <b>checked-in</b> or <b>non-refundable</b>. In any other case a <b>Proforma invoice</b> is issued.</div>
      </div>
      <div className="grid grid--4" style={{ marginBottom: 18 }}>
        <Metric accent label="Invoiced (total)" value={"€" + totals.invoiced.toLocaleString()} hint={ROWS.filter((r) => r.type === "Invoice").length + " invoices"} />
        <Metric label="Proforma outstanding" value={"€" + totals.proforma.toLocaleString()} hint="Awaiting check-in" />
        <Metric label="Overdue" value={"€" + totals.overdue.toLocaleString()} hint={ROWS.filter((r) => r.status === "Overdue").length + " invoices"} />
        <Metric label="Paid" value={"€" + totals.paid.toLocaleString()} hint={totals.invoiced ? Math.round(totals.paid / totals.invoiced * 100) + "% collected" : "-"} />
      </div>
      <div className="filter-bar" data-comment-anchor="07996a20c8-div-550-7">
        <input className="input input--search" placeholder="Search by invoice, agency or amount…" style={{ width: 320 }} />
        <Segmented value={docType} onChange={setDocType} options={[
        { value: "all", label: "All" }, { value: "invoice", label: "Invoices" }, { value: "proforma", label: "Proforma" }]
        } />
        <select className="select"><option>All statuses</option><option>Proforma</option><option>Sent</option><option>Paid</option><option>Overdue</option></select>
        <select className="select"><option>This month</option><option>This quarter</option><option>This year</option><option>All time</option></select>
        <span className="spacer" />
        <Button kind="secondary" icon={<Icon.Download />}>Export</Button>
        <Button kind="primary" icon={<Icon.Plus />} onClick={() => {
          var aidRaw = window.prompt("Agency id for this invoice?");
          if (!aidRaw) return;
          var amount = Number(window.prompt("Total amount (EUR)?", "0"));
          var invType = window.prompt("Invoice type? (Invoice|Proforma)", "Invoice");
          window.TrekkoAPI.createManualInvoice(aidRaw, { total_amount: amount, invoice_type: invType })
            .then(function () { toast({ title: "Invoice creation queued", body: invType + " · €" + amount + " · agency #" + aidRaw, tone: "success" }); })
            .catch(function (e) { toast({ title: "Create invoice failed", body: String(e && e.message || e), tone: "danger" }); });
        }}>New invoice</Button>
      </div>

      <div className="tbl-wrap tbl-wrap--linked">
        <table className="tbl">
          <thead><tr><th>Document</th><th>Type</th><th>Agency</th><th>Trigger</th><th>Issued</th><th>Due</th><th className="num">Bookings</th><th className="num">Total</th><th>Status</th><th className="col-actions"></th></tr></thead>
          <tbody>
            {filtered.map((r) =>
            <tr key={r.id}>
                <td className="mono"><a href="#" onClick={(e) => {e.preventDefault();toast({ title: "Open " + r.id, tone: "success" });}}>{r.id}</a></td>
                <td>{r.type === "Invoice" ? <Badge tone="indigo">Invoice</Badge> : <Badge tone="neutral">Proforma</Badge>}</td>
                <td className="bold">{r.agency}</td>
                <td className="muted tiny">{r.trigger}</td>
                <td className="mono">{r.issued}</td>
                <td className="mono">{r.due}</td>
                <td className="num mono">{r.bookings}</td>
                <td className="num mono bold">€{r.total.toLocaleString()}</td>
                <td>{r.status === "Paid" ? <Badge tone="success">Paid</Badge> :
                r.status === "Sent" ? <Badge tone="info">Sent</Badge> :
                r.status === "Overdue" ? <Badge tone="danger">Overdue</Badge> :
                <Badge tone="warning">Proforma</Badge>}</td>
                <td className="col-actions">
                  <div className="row" style={{ gap: 4, justifyContent: "flex-end" }}>
                    <Button kind="ghost" size="sm" iconOnly icon={<Icon.Doc />} title="Download PDF" onClick={() => {
                      var invNo = r.invoice_id || r.id;
                      if (invNo && window.TrekkoAPI && window.TrekkoAPI.downloadBookingInvoice) {
                        // Strip 'INV-' prefix if present
                        var num = String(invNo).replace(/^INV-/, "");
                        window.TrekkoAPI.downloadBookingInvoice(num)
                          .then(function () { toast({ title: "Downloaded " + r.id, tone: "success" }); })
                          .catch(function (e) { toast({ title: "Download failed", body: String(e && e.message || e), tone: "danger" }); });
                      } else {
                        toast({ title: "Download not available", tone: "danger" });
                      }
                    }} />
                    <Button kind="ghost" size="sm" iconOnly icon={<Icon.Mail />} title="Resend" onClick={() => {
                      window.TrekkoAPI.resendInvoice(r.id)
                        .then(function () { toast({ title: "Resend queued", body: r.id, tone: "success" }); })
                        .catch(function (e) { toast({ title: "Resend failed", body: String(e && e.message || e), tone: "danger" }); });
                    }} />
                    {r.type === "Proforma" && <Button kind="ghost" size="sm" iconOnly icon={<Icon.Refresh />} title="Convert to invoice" onClick={() => {
                      if (!window.confirm("Convert " + r.id + " from Proforma to Invoice?")) return;
                      window.TrekkoAPI.convertInvoice(r.id)
                        .then(function () { toast({ title: "Conversion queued", body: r.id, tone: "success" }); })
                        .catch(function (e) { toast({ title: "Convert failed", body: String(e && e.message || e), tone: "danger" }); });
                    }} />}
                  </div>
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
    </>);

}

Object.assign(window, { PageTravelGroupsEnhanced, PagePaymentsEnhanced });