/* global React, Icon, Badge, Tag, Avatar, Button, Field, Toggle, Tabs, Segmented, Card, Metric, Modal, Pager, Sparkline, ProgressBar, toast */

var { useState, useMemo } = React;

// helper: status badge for booking statuses
function StatusBadge({ status }) {
  const map = {
    Paid: { tone: "success", label: "Paid" },
    Overdue: { tone: "danger", label: "Overdue" },
    Upcoming: { tone: "warning", label: "Upcoming" },
    Cancelled: { tone: "neutral", label: "Cancelled" },
    Success: { tone: "success", label: "Success" },
    Pending: { tone: "warning", label: "Pending" },
    Failed: { tone: "danger", label: "Failed" },
    Active: { tone: "success", label: "Active" },
    Suspended: { tone: "danger", label: "Suspended" },
    Approved: { tone: "success", label: "Approved" },
    Rejected: { tone: "danger", label: "Rejected" },
    Draft: { tone: "neutral", label: "Draft" }
  };
  const m = map[status] || { tone: "neutral", label: status };
  return <Badge tone={m.tone}>{m.label}</Badge>;
}

// ============================================================
// FILTER DRAWER
// ============================================================
function FilterDrawer({ open, onClose, onApply }) {
  const [filterAgencies, setFilterAgencies] = React.useState((window.MOCK && window.MOCK.TRAVEL_AGENCIES) || []);
  React.useEffect(() => {
    if (!open || !window.TrekkoAPI) return;
    window.TrekkoAPI.getAgencies().then((rows) => { if (rows && rows.length) setFilterAgencies(rows); });
  }, [open]);
  if (!open) return null;
  return (
    <>
      <div className="drawer-veil" onClick={onClose} />
      <div className="drawer">
        <div className="modal__head">
          <h3 className="modal__title">Filter bookings</h3>
          <button className="modal__close" onClick={onClose}><Icon.X /></button>
        </div>
        <div className="modal__body" style={{ padding: 22, overflowY: "auto" }}>
          <Field label="Date range">
            <div className="row">
              <input className="input" placeholder="From" type="date" />
              <input className="input" placeholder="To" type="date" />
            </div>
          </Field>
          <div style={{ height: 14 }} />
          <Field label="Service type">
            <div className="row" style={{ gap: 6, flexWrap: "wrap" }}>
              {["Hotels", "Rental Cars", "Transfer", "Flight"].map((t) =>
              <label key={t} className="row" style={{ gap: 6, padding: "5px 10px", border: "1px solid var(--border)", borderRadius: 6, cursor: "pointer" }}>
                  <input className="checkbox" type="checkbox" defaultChecked /> <span>{t}</span>
                </label>
              )}
            </div>
          </Field>
          <div style={{ height: 14 }} />
          <Field label="Status">
            <div className="row" style={{ gap: 6, flexWrap: "wrap" }}>
              {["Paid", "Overdue", "Upcoming", "Cancelled"].map((s) =>
              <label key={s} className="row" style={{ gap: 6, padding: "5px 10px", border: "1px solid var(--border)", borderRadius: 6, cursor: "pointer" }}>
                  <input className="checkbox" type="checkbox" /> <span>{s}</span>
                </label>
              )}
            </div>
          </Field>
          <div style={{ height: 14 }} />
          <Field label="Travel agency">
            <select className="select"><option>All agencies</option>{filterAgencies.map((a) => <option key={a.id}>{a.name}</option>)}</select>
          </Field>
          <div style={{ height: 14 }} />
          <Field label="Amount range (€)">
            <div className="row">
              <input className="input" type="number" placeholder="Min" />
              <span className="muted">to</span>
              <input className="input" type="number" placeholder="Max" />
            </div>
          </Field>
          <div style={{ height: 14 }} />
          <Field label="Destination">
            <input className="input" placeholder="Search destination…" />
          </Field>
          <div style={{ height: 14 }} />
          <Field label="Quick presets">
            <div className="row" style={{ gap: 6, flexWrap: "wrap" }}>
              {["Today", "Last 7 days", "Last 30 days", "This quarter", "Year to date"].map((t) =>
              <button key={t} className="btn btn--secondary btn--sm">{t}</button>
              )}
            </div>
          </Field>
        </div>
        <div className="modal__foot">
          <Button kind="ghost" onClick={onClose}>Clear all</Button>
          <span className="spacer" />
          <Button kind="secondary" onClick={onClose}>Cancel</Button>
          <Button kind="primary" onClick={() => {onApply();onClose();}}>Apply filters</Button>
        </div>
      </div>
    </>);

}

// ============================================================
// PAGE: BOOKINGS
// ============================================================
function PageBookings({ onNav, onOpenDetail }) {
  const [bookings, setBookings] = useState((window.MOCK && window.MOCK.BOOKINGS) || []);
  const [agenciesList, setAgenciesList] = useState((window.MOCK && window.MOCK.TRAVEL_AGENCIES) || []);
  React.useEffect(() => {
    if (!window.TrekkoAPI) return;
    window.TrekkoAPI.getBookings().then((rows) => { if (rows && rows.length) setBookings(rows); });
    window.TrekkoAPI.getAgencies().then((rows) => { if (rows && rows.length) setAgenciesList(rows); });
  }, []);
  const [tab, setTab] = useState("agent"); // agent | vendor | car | accomm
  const [page, setPage] = useState(1);
  const [filterOpen, setFilterOpen] = useState(false);
  const [selected, setSelected] = useState([]);
  const [search, setSearch] = useState("");
  const [statusF, setStatusF] = useState("");
  const PAGE_SIZE = 8;

  // Bookings filtered by tab & search & status
  const rows = useMemo(() => {
    let r = bookings;
    if (tab === "car") r = r.filter((b) => b.type.code === "car");
    if (tab === "accomm") r = r.filter((b) => b.type.code === "hotel");
    if (tab === "transfer") r = r.filter((b) => b.type.code === "tr");
    if (tab === "lounge") r = r.filter((b) => b.type.code === "vipl");
    if (tab === "vipair") r = r.filter((b) => b.type.code === "vipas");
    if (tab === "tour") r = r.filter((b) => b.type.code === "ptour");
    if (search) r = r.filter((b) => (b.shortId + b.agency + b.destination).toLowerCase().includes(search.toLowerCase()));
    if (statusF) r = r.filter((b) => b.status === statusF);
    return r;
  // CRITICAL: bookings MUST be in the dep array. Without it, when the
  // useEffect-driven setBookings(realRows) fires, this useMemo keeps
  // returning the original mock filter result -> tabs show 72 (real
  // count) but the table still renders the 48 mock rows. Caught live.
  }, [tab, search, statusF, bookings]);
  const slice = rows.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);

  const allSel = slice.every((b) => selected.includes(b.id)) && slice.length > 0;
  const toggleAll = () => {
    if (allSel) setSelected((s) => s.filter((id) => !slice.some((b) => b.id === id)));else
    setSelected((s) => Array.from(new Set([...s, ...slice.map((b) => b.id)])));
  };

  return (
    <div data-comment-anchor="4a1efe2e93-div-132-5">
      <div className="page-head">
        <div>
          <h1 className="page-head__title">Bookings</h1>
          <div className="page-head__sub">Manage all bookings across agencies, vendors and car companies.</div>
        </div>
        <div className="page-head__actions">
          <Button kind="secondary" icon={<Icon.Download />} onClick={() => {
            window.TrekkoAPI.exportBookingsCsv(1000)
              .then(function () { toast({ title: "Bookings CSV downloaded", body: "Capped at 1000 rows.", tone: "success" }); })
              .catch(function (e) { toast({ title: "Export failed", body: String(e && e.message || e), tone: "danger" }); });
          }}>Export</Button>
        </div>
      </div>

      <Tabs
        active={tab}
        onChange={(t) => {setTab(t);setPage(1);setSelected([]);}}
        tabs={[
        { id: "agent", label: "All", count: bookings.length },
        { id: "accomm", label: "Accommodation", count: bookings.filter((b) => b.type.code === "hotel").length },
        { id: "car", label: "Car Rental", count: bookings.filter((b) => b.type.code === "car").length },
        { id: "transfer", label: "Transfer", count: bookings.filter((b) => b.type.code === "tr").length },
        { id: "lounge", label: "Airport Lounge", count: bookings.filter((b) => b.type.code === "vipl").length },
        { id: "vipair", label: "VIP Airport", count: bookings.filter((b) => b.type.code === "vipas").length },
        { id: "tour", label: "Private Tours", count: bookings.filter((b) => b.type.code === "ptour").length }]
        } />
      

      <div className="grid grid--3" style={{ marginBottom: 14 }}>
        <Metric accent label="Outstanding Amount (€)" value="€23,000" delta="−4.2% WoW" deltaDir="down" />
        <Metric label="Total Receivables (€)" value="€23,000" hint="In open balances" />
        <Metric label="Overdue Payments" value="5" delta="€23,000 total" deltaDir="down" hint="Action required" />
      </div>

      {/* Incoming payments by window — for the financial controller */}
      <div className="grid grid--4" style={{ marginBottom: 18 }}>
        <Metric label="Due in 7 days" value="€18,540" hint="12 invoices" />
        <Metric label="Due in 14 days" value="€31,200" hint="21 invoices" />
        <Metric label="Due in 21 days" value="€44,800" hint="29 invoices" />
        <Metric label="Due in 30 days" value="€62,400" hint="38 invoices" />
      </div>

      {/* Filter bar */}
      <div className="filter-bar">
        <input className="input input--search" placeholder="Search by booking ID, agency or destination…" value={search} onChange={(e) => setSearch(e.target.value)} style={{ width: 320 }} />
        <select className="select" value={statusF} onChange={(e) => setStatusF(e.target.value)}>
          <option value="">All statuses</option>
          {window.MOCK.STATUSES.map((s) => <option key={s}>{s}</option>)}
        </select>
        <select className="select"><option>All service types</option><option>Hotels</option><option>Rental Cars</option><option>Transfer</option><option>Flight</option></select>
        <select className="select"><option>All markets</option><option>Iberia</option><option>DACH</option><option>UK</option><option>LATAM</option></select>
        <Button kind="secondary" icon={<Icon.Filter />} onClick={() => setFilterOpen(true)}>More filters</Button>
        <span className="spacer" />
      </div>

      {/* Bulk bar */}
      {selected.length > 0 &&
      <div className="bulk-bar">
          <span className="bulk-bar__count">{selected.length} selected</span>
          <button className="btn btn--ghost btn--sm" onClick={() => setSelected([])}>Clear</button>
          <div className="bulk-bar__actions">
            <Button kind="secondary" size="sm" icon={<Icon.Download />} onClick={() => {
              window.TrekkoAPI.exportBookingsCsv(1000)
                .then(function () { toast({ title: "Bookings CSV downloaded", body: "Capped at 1000 rows (selection-specific export pending).", tone: "success" }); })
                .catch(function (e) { toast({ title: "Export failed", body: String(e && e.message || e), tone: "danger" }); });
            }}>Export selected</Button>
            <Button kind="success" size="sm" icon={<Icon.Check />} onClick={() => {
              if (!window.confirm("Mark " + selected.length + " booking(s) as paid? This is a real DB mutation.")) return;
              if (!window.TrekkoAPI || !window.TrekkoAPI.bulkMarkBookingsPaid) {
                toast({ title: "Bulk mark-as-paid not available", tone: "danger" });
                return;
              }
              window.TrekkoAPI.bulkMarkBookingsPaid(selected)
                .then(function (r) { toast({ title: "Marked " + (r && r.updated || 0) + " as paid", body: "of " + selected.length + " selected", tone: "success" }); setSelected([]); })
                .catch(function (e) { toast({ title: "Bulk mark-as-paid failed", body: String(e && e.message || e), tone: "danger" }); });
            }}>Mark as paid</Button>
            <Button kind="warning" size="sm" icon={<Icon.Send />} onClick={() => {
              if (!window.confirm("Queue reminder emails for " + selected.length + " booking(s)? (Backend queues now; real SES send pending worker integration.)")) return;
              if (!window.TrekkoAPI || !window.TrekkoAPI.bulkSendReminders) { toast({ title: "Endpoint unavailable", tone: "danger" }); return; }
              window.TrekkoAPI.bulkSendReminders(selected)
                .then(function (r) { toast({ title: "Queued " + (r && r.queued || 0) + " reminders", tone: "success" }); })
                .catch(function (e) { toast({ title: "Reminder queue failed", body: String(e && e.message || e), tone: "danger" }); });
            }}>Send reminders</Button>
          </div>
        </div>
      }

      {/* Table */}
      <div className="tbl-wrap tbl-wrap--linked">
        <table className="tbl">
          <thead>
            <tr>
              <th className="col-check"><input className="checkbox" type="checkbox" checked={allSel} onChange={toggleAll} /></th>
              <th>Booking ID</th>
              <th>Service</th>
              <th>Travel agency</th>
              <th>Email</th>
              <th>Booking date</th>
              <th>Travel date</th>
              <th className="num">Reminders</th>
              <th>Payment copy</th>
              <th className="num">Amount</th>
              <th>Status</th>
              <th className="col-actions"></th>
            </tr>
          </thead>
          <tbody>
            {slice.map((b) =>
            <tr key={b.id}>
                <td className="col-check">
                  <input className="checkbox" type="checkbox"
                checked={selected.includes(b.id)}
                onChange={() => setSelected((s) => s.includes(b.id) ? s.filter((x) => x !== b.id) : [...s, b.id])} />
                </td>
                <td className="mono"><a href="#" onClick={(e) => {e.preventDefault();onOpenDetail && onOpenDetail(b);}}>{b.shortId}</a></td>
                <td><Tag kind={b.type.tag}>{b.type.label}</Tag></td>
                <td className="bold">{b.agency}</td>
                <td className="muted">{b.agencyEmail}</td>
                <td className="mono">{b.bookingDate}</td>
                <td className="mono">{b.travelDate}</td>
                <td className="num mono">{b.reminders}</td>
                <td><a href="#" onClick={(e) => e.preventDefault()}><Icon.Doc size={12} style={{ verticalAlign: -2 }} /> View file</a></td>
                <td className="num mono bold">€{Number(b.amount || 0).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</td>
                <td><StatusBadge status={b.status} /></td>
                <td className="col-actions">
                  <Button kind="secondary" size="sm" onClick={() => onOpenDetail && onOpenDetail(b)}>Update</Button>
                </td>
              </tr>
            )}
            {slice.length === 0 && <tr><td colSpan="12" className="tbl-empty">No bookings match your filters.</td></tr>}
          </tbody>
        </table>
      </div>
      <Pager page={page} pageSize={PAGE_SIZE} total={rows.length} onPage={setPage} />

      <FilterDrawer open={filterOpen} onClose={() => setFilterOpen(false)} onApply={() => {}} />
    </div>);

}

// ============================================================
// PAGE: BOOKING DETAIL
// ============================================================
function PageBookingDetail({ booking, onNav }) {
  const [tab, setTab] = useState("overview");
  const [editing, setEditing] = useState(false);
  const [fallback, setFallback] = useState((window.MOCK && window.MOCK.BOOKINGS && window.MOCK.BOOKINGS[0]) || {});
  // Real backend detail for the panel below the header. The panel was
  // showing mock 'Marriott Marbella' / 'HCN-4471892' / '#1173-798026590'
  // even when the header showed the real booking. Fetch via
  // /bookings/get_accommodation_booking_details and merge over the mock.
  const [bDetail, setBDetail] = useState(null);
  // When deep-linked via /bookings/<shortId> the entity is a stub with
  // only { shortId } - we still need a real row for type/agency/etc.
  const _stubBookingForLoad = booking && !booking.type && booking.shortId;
  React.useEffect(() => {
    if ((booking && !_stubBookingForLoad) || !window.TrekkoAPI) return;
    window.TrekkoAPI.getBookings().then((rows) => {
      if (!rows || !rows.length) return;
      if (_stubBookingForLoad) {
        const sid = String(booking.shortId);
        const hit = rows.find((r) => String(r.shortId) === sid);
        setFallback(hit || rows[0]);
      } else {
        setFallback(rows[0]);
      }
    });
  }, [booking, _stubBookingForLoad]);
  React.useEffect(() => {
    var src = booking || fallback;
    if (!src || !src.shortId || !window.TrekkoAPI) { setBDetail(null); return; }
    window.TrekkoAPI.getBookingDetail(src.shortId).then(setBDetail);
  }, [booking, fallback]);
  // Merge: real backend wins over the row data, row data wins over the empty mock.
  // When deep-linked via /bookings/<shortId> the entity is just { shortId },
  // so the type/agency/travelDate fields all come from the fallback row.
  const stubBooking = booking && !booking.type && booking.shortId;
  const baseB = stubBooking ? Object.assign({}, fallback, booking) : (booking || fallback);
  const b = Object.assign({}, baseB, bDetail ? {
    agency: bDetail.agent_name || baseB.agency,
    agencyEmail: bDetail.user_email || baseB.agencyEmail,
    bookingDate: bDetail.created_on ? bDetail.created_on.slice(0, 10) : baseB.bookingDate,
    travelDate: bDetail.check_in || baseB.travelDate,
    checkOut: bDetail.check_out || baseB.checkOut,
    destination: bDetail.accommodation_name || baseB.destination,
    amount: bDetail.total_price_eur != null ? bDetail.total_price_eur : (bDetail.total_price != null ? bDetail.total_price : baseB.amount),
    profit: bDetail.commission_total != null ? bDetail.commission_total : baseB.profit,
    status: bDetail.canceled ? "Cancelled" : (bDetail.paid ? "Paid" : (bDetail.overdue ? "Overdue" : (bDetail.status || baseB.status))),
    netPrice: bDetail.net_price_no_additional_services,
    invoiceId: bDetail.invoice_id,
    paymentStatus: bDetail.payment_status,
    paymentMethod: bDetail.paid_by,
    paymentDue: bDetail.payment_due,
    paidOn: bDetail.paid_on,
    city: bDetail.city,
    country: bDetail.country_route,
    cancellationFee: bDetail.cancellation_fee,
    freeCancelUntil: bDetail.free_cancellation_until,
    realDetail: bDetail,
  } : {});

  return (
    <div data-comment-anchor="52165e25e7-div-256-5">
      <div className="page-head">
        <div>
          <div style={{ display: "flex", gap: 10, alignItems: "center", marginBottom: 6 }}>
            <button className="btn btn--ghost btn--sm" onClick={() => onNav("bookings")}><Icon.ChevronLeft /> Bookings</button>
            <span className="muted">·</span>
            <span className="mono muted">Booking #{b.shortId}</span>
            <StatusBadge status={b.status} />
          </div>
          <h1 className="page-head__title" style={{ marginBottom: 2 }}>
            {b.agency} <span className="muted" style={{ fontWeight: 500, fontSize: 18 }}>· {b.type.label}</span>
          </h1>
          <div className="page-head__sub">Travel date {b.travelDate} · Booked {b.bookingDate} · {b.destination}</div>
        </div>
        <div className="page-head__actions">
          <Button kind="secondary" icon={<Icon.Doc />} onClick={() => {
            var invNo = b.invoiceId || (b.realDetail && (b.realDetail.invoice_id || b.realDetail.invoice_number)) || b.shortId;
            if (!invNo) { toast({ title: "No invoice number on this booking", tone: "danger" }); return; }
            if (!window.TrekkoAPI || !window.TrekkoAPI.downloadBookingInvoice) {
              toast({ title: "Invoice download not available", tone: "danger" });
              return;
            }
            window.TrekkoAPI.downloadBookingInvoice(invNo)
              .then(function () { toast({ title: "Invoice downloaded", tone: "success" }); })
              .catch(function (e) { toast({ title: "Invoice download failed", body: String(e && e.message || e), tone: "danger" }); });
          }}>Download invoice</Button>
          {!editing && <Button kind="secondary" icon={<Icon.Edit />} onClick={() => setEditing(true)}>Edit booking</Button>}
          {editing &&
          <>
              <Button kind="secondary" onClick={() => setEditing(false)}>Cancel</Button>
              <Button kind="primary" icon={<Icon.Check />} onClick={() => {
                if (!window.TrekkoAPI || !window.TrekkoAPI.directModifyBooking) {
                  toast({ title: "Save not yet available", body: "directModifyBooking endpoint not wired", tone: "warning" });
                  setEditing(false);
                  return;
                }
                // Stub: collect edits from the form and POST. For now, no inputs
                // are tracked granularly in this prototype so we just close the
                // edit mode and notify the user that field-level edits aren't
                // persisted yet.
                toast({ title: "Field-level edits not yet persisted", body: "Use Modify Booking Requests for now", tone: "warning" });
                setEditing(false);
              }}>Save changes</Button>
            </>
          }
          <Button kind="danger" icon={<Icon.X />} onClick={() => {
            if (b.status === "Cancelled") { toast({ title: "Booking already cancelled", tone: "warning" }); return; }
            var reason = window.prompt("Cancellation reason?", "Cancelled via CRM");
            if (reason == null) return; // user cancelled the prompt
            if (!window.TrekkoAPI || !window.TrekkoAPI.cancelBooking) {
              toast({ title: "Cancel not available", tone: "danger" });
              return;
            }
            window.TrekkoAPI.cancelBooking(b.shortId, reason)
              .then(function () { toast({ title: "Booking cancelled", body: "#" + b.shortId, tone: "success" }); })
              .catch(function (e) { toast({ title: "Cancel failed", body: String(e && e.message || e), tone: "danger" }); });
          }}>Cancel booking</Button>
        </div>
      </div>

      <Tabs
        active={tab}
        onChange={setTab}
        tabs={[
        { id: "overview", label: "Overview" },
        { id: "passengers", label: "Passengers" },
        { id: "log", label: "Log history" },
        { id: "notes", label: "Internal notes" }]
        } />
      

      {tab === "overview" && <OverviewTab b={b} editing={editing} />}
      {tab === "passengers" && <PassengersTab b={b} editing={editing} />}
      {tab === "log" && <LogTab />}
      {tab === "notes" && <NotesTab />}
    </div>);

}

function DataRow({ label, value, editing, type = "text" }) {
  return (
    <>
      <dt>{label}</dt>
      <dd>
        {editing ?
        type === "select" ?
        <select className="select" defaultValue={value} style={{ height: 28 }}><option>{value}</option><option>Other…</option></select> :
        <input className="input" defaultValue={value} style={{ height: 28 }} /> :
        value || <span className="muted">—</span>}
      </dd>
    </>);

}

function OverviewTab({ b, editing }) {
  const code = b.type.code;
  const [policyOpen, setPolicyOpen] = React.useState(null);
  // service-specific detail fields. Hotel detail rows are filled from
  // the real /get_accommodation_booking_details payload (b.realDetail).
  // Other service types still fall back to mock until backend exposes
  // car/tr/vipl/vipas/ptour booking detail endpoints.
  const rd = b.realDetail || {};
  // Compute nights from real check-in/check-out (millisecond diff /
  // 24h) when both are present. Falls back to "—" so we never invent a
  // count when the data isn't there.
  let nights = "—";
  if (rd.check_in && rd.check_out) {
    const a = new Date(rd.check_in), c = new Date(rd.check_out);
    const d = Math.round((c - a) / 86400000);
    if (Number.isFinite(d) && d > 0) nights = String(d);
  }
  const roomsLine = (() => {
    const r = rd.rooms_count != null ? rd.rooms_count : (rd.rooms || rd.no_of_rooms);
    const ad = rd.adults != null ? rd.adults : rd.adults_count;
    const ch = rd.children != null ? rd.children : rd.children_count;
    if (r == null && ad == null && ch == null) return "—";
    const parts = [];
    if (r != null) parts.push(`${r} room${r === 1 ? "" : "s"}`);
    if (ad != null) parts.push(`${ad} adult${ad === 1 ? "" : "s"}`);
    if (ch != null && ch > 0) parts.push(`${ch} child${ch === 1 ? "" : "ren"}`);
    return parts.join(" · ") || "—";
  })();
  const detailFields = {
    hotel: [
    ["Hotel confirmation no.", rd.hcn || rd.accommodation_booking_id || rd.booking_reference || "—", "text"],
    ["Hotel name", rd.accommodation_name || b.destination || "—", "text"],
    ["Check-in", rd.check_in || b.travelDate || "—", "text"],
    ["Check-out", rd.check_out || b.checkOut || "—", "text"],
    ["Nights", nights, "text"],
    ["Rooms", roomsLine, "text"],
    ["Special requests", rd.special_requests || rd.remarks || "—", "text"]],

    // car/tr/vipl/vipas/ptour: backend doesn't yet expose per-service
    // booking detail (only accommodation has /get_accommodation_booking_details),
    // so we leave the fields with "—" placeholders. Once the backend
    // exposes those endpoints, populate from rd.* like the hotel block above.
    car: [
    ["Rental confirmation no.", "—", "text"],
    ["Supplier", "—", "text"],
    ["Vehicle category", "—", "text"],
    ["Pick-up location", "—", "text"],
    ["Pick-up date/time", b.travelDate || "—", "text"],
    ["Drop-off location", "—", "text"],
    ["Drop-off date/time", b.checkOut || "—", "text"],
    ["Rental days", "—", "text"],
    ["Extras", "—", "text"],
    ["Driver name", "—", "text"]],

    tr: [
    ["Transfer confirmation no.", "—", "text"],
    ["Vendor", "—", "text"],
    ["Route", "—", "text"],
    ["Pick-up date/time", b.travelDate || "—", "text"],
    ["Vehicle", "—", "text"],
    ["Passengers", "—", "text"],
    ["Luggage", "—", "text"],
    ["Flight number", "—", "text"],
    ["Driver name", "—", "text"],
    ["Driver phone", "—", "text"]],

    vipl: [
    ["Lounge confirmation no.", "—", "text"],
    ["Vendor", "—", "text"],
    ["Airport · Terminal", "—", "text"],
    ["Lounge name", "—", "text"],
    ["Access date/time", b.travelDate || "—", "text"],
    ["Duration", "—", "text"],
    ["Passengers", "—", "text"],
    ["Services", "—", "text"]],

    vipas: [
    ["Service confirmation no.", "—", "text"],
    ["Vendor", "—", "text"],
    ["Airport · Terminal", "—", "text"],
    ["Service type", "—", "text"],
    ["Service date/time", b.travelDate || "—", "text"],
    ["Passengers", "—", "text"],
    ["Meeting point", "—", "text"],
    ["Contact person", "—", "text"]],

    ptour: [
    ["Tour confirmation no.", "—", "text"],
    ["Vendor", "—", "text"],
    ["Tour name", "—", "text"],
    ["Tour date", b.travelDate || "—", "text"],
    ["Start time", "—", "text"],
    ["Duration", "—", "text"],
    ["Participants", "—", "text"],
    ["Guide language", "—", "text"],
    ["Meeting point", "—", "text"]]

  };
  const fields = detailFields[code] || detailFields.hotel;
  const cardTitle = {
    hotel: "Accommodation details", car: "Car rental details", tr: "Transfer details",
    vipl: "Airport lounge details", vipas: "VIP airport service details", ptour: "Private tour details"
  }[code] || "Booking details";

  // pricing
  const sell = b.amount;
  const net = Math.round(sell * 0.7);
  const profit = sell - net;
  const margin = (profit / sell * 100).toFixed(1);

  return (
    <div className="grid" style={{ gridTemplateColumns: "1.4fr 1fr", gap: 18 }}>
      <div className="col" style={{ gap: 18 }}>
        <Card title={cardTitle} sub={`${b.type.label} · ${b.agency}`}>
          <dl className="dl">
            <DataRow label="Booking number" value={"#" + b.shortId + "-798026590"} editing={false} />
            {fields.map(([label, value, type]) =>
            <DataRow key={label} label={label} value={value} editing={editing} type={type} />
            )}
          </dl>
        </Card>

        {code === "hotel" &&
        <Card title="Rooms & rate plans" sub="Each room can have a different board basis & cancellation policy"
        actions={editing ? <Button kind="secondary" size="sm" icon={<Icon.Plus />} onClick={() => {
          var rt = window.prompt("Room type to add?", "Standard double");
          if (!rt) return;
          var adults = Number(window.prompt("Adults?", "2"));
          var children = Number(window.prompt("Children? (0 if none)", "0") || 0);
          window.TrekkoAPI.addRoomToBooking(b.shortId, { room_type: rt, adults: adults, children: children })
            .then(function () { toast({ title: "Add-room queued", body: rt + " (audit-log, real append pending)", tone: "success" }); })
            .catch(function (e) { toast({ title: "Add room failed", body: String(e && e.message || e), tone: "danger" }); });
        }}>Add room</Button> : null} flush>
          <table className="tbl">
            <thead><tr><th>Room</th><th>Type</th><th>Occupancy</th><th>Board basis</th><th>Policy</th><th className="num">Net</th><th className="num">Sell</th></tr></thead>
            <tbody>
              <tr>
                <td className="bold">Room 1</td>
                <td>Deluxe Sea-View</td>
                <td>2 adults</td>
                <td><Badge tone="info">Bed & Breakfast</Badge></td>
                <td><button onClick={() => setPolicyOpen({ room: "Room 1 · Deluxe Sea-View", type: "Refundable" })} style={{ background: "none", border: 0, padding: 0, cursor: "pointer" }}><Badge tone="success">Refundable</Badge></button></td>
                <td className="num mono">€520</td>
                <td className="num mono bold">€742</td>
              </tr>
              <tr>
                <td className="bold">Room 2</td>
                <td>Family Room</td>
                <td>2 children</td>
                <td><Badge tone="neutral">Room Only</Badge></td>
                <td><button onClick={() => setPolicyOpen({ room: "Room 2 · Family Room", type: "Non-refundable" })} style={{ background: "none", border: 0, padding: 0, cursor: "pointer" }}><Badge tone="danger">Non-refundable</Badge></button></td>
                <td className="num mono">€340</td>
                <td className="num mono bold">€486</td>
              </tr>
            </tbody>
          </table>
        </Card>}

        <Card title="Pricing & profit" sub="Net cost vs. sell price">
          <dl className="dl">
            <DataRow label="Net price (our cost)" value={"€" + net.toLocaleString()} editing={editing} />
            <DataRow label="Sell price (to agency)" value={"€" + sell.toLocaleString()} editing={editing} />
            <dt>Profit / margin</dt>
            <dd className="bold" style={{ color: "var(--success)" }}>€{profit.toLocaleString()} · {margin}%</dd>
            <DataRow label="Currency" value="EUR" editing={editing} type="select" />
            <DataRow label="Payment status" value={b.status} editing={false} />
          </dl>
        </Card>

        {code !== "hotel" &&
        <Card title="Cancellation policy" sub="Click to see full conditions" flush>
          <div style={{ padding: 16 }}>
            <button onClick={() => setPolicyOpen({ room: b.type.label, type: b.amount % 2 === 0 ? "Refundable" : "Non-refundable" })} style={{ background: "none", border: 0, padding: 0, cursor: "pointer", display: "flex", alignItems: "center", gap: 10 }}>
              {b.amount % 2 === 0
                ? <Badge tone="success">Refundable</Badge>
                : <Badge tone="danger">Non-refundable</Badge>}
              <span className="muted tiny">View {b.type.label.toLowerCase()} cancellation conditions →</span>
            </button>
          </div>
        </Card>}

        <Card title="User & contract">
          <dl className="dl">
            <DataRow label="User email" value="info@staytick.com" editing={editing} />
            <DataRow label="Contract number" value="B2B-102666" editing={editing} />
            <DataRow label="Invoice ID" value="INV-2025-0098" editing={false} />
            <DataRow label="Created on" value="Jun 4, 2024 — 17:16" editing={false} />
            <DataRow label="Free cancellation" value="Jul 21, 2024 — 12:00" editing={editing} />
            <DataRow label="Cancellation without penalty" value="Yes" editing={editing} type="select" />
          </dl>
        </Card>
      </div>

      <div className="col" style={{ gap: 18 }} data-comment-anchor="d6a22863cf-div-462-7">
        <Card title="Status" sub="Operational state">
          <div className="row" style={{ gap: 8, marginBottom: 12 }}>
            <StatusBadge status={b.status} />
            <span className="muted tiny">Updated 2 hrs ago by Maria Lopez</span>
          </div>
          <ul style={{ listStyle: "none", padding: 0, margin: 0, fontSize: 13 }}>
            <Step label="Booking created" done time={b.bookingDate} />
            <Step label="Payment requested" done time={b.paymentSent} />
            <Step label="Payment received" done={b.status === "Paid"} time={b.status === "Paid" ? b.paymentSent : "—"} />
            <Step label="Service confirmed by vendor" done={b.status !== "Cancelled"} time={b.status === "Cancelled" ? "—" : "Today"} />
            <Step label="Travel completed" done={false} time={b.travelDate} pending />
          </ul>
        </Card>

        <Card title="Customer">
          <div className="row" style={{ gap: 12, marginBottom: 12 }}>
            <Avatar name={b.agency} size="lg" />
            <div>
              <div className="bold">{b.agency}</div>
              <div className="tiny muted">{b.agencyEmail}</div>
              <div className="tiny muted">+34 690 530 5856</div>
            </div>
          </div>
          <div className="grid grid--2" style={{ gap: 8 }}>
            <Button kind="secondary" size="sm" icon={<Icon.Mail />} onClick={() => {
              if (b.agencyEmail) { window.location.href = "mailto:" + b.agencyEmail + "?subject=Booking%20%23" + b.shortId; }
              else { toast({ title: "No email on file for this agency", tone: "warning" }); }
            }}>Email</Button>
            <Button kind="secondary" size="sm" icon={<Icon.Phone />} onClick={() => {
              var phone = b.agencyPhone || (b.realDetail && b.realDetail.agency_phone);
              if (phone) { window.location.href = "tel:" + String(phone).replace(/[^+0-9]/g, ""); }
              else { toast({ title: "No phone on file for this agency", tone: "warning" }); }
            }}>Call</Button>
          </div>
        </Card>
      </div>

      {policyOpen &&
      <Modal open title={`Cancellation policy · ${policyOpen.room}`} onClose={() => setPolicyOpen(null)}
      footer={<Button kind="primary" onClick={() => setPolicyOpen(null)}>Close</Button>}>
        <div className="row" style={{ gap: 8, marginBottom: 14 }}>
          {policyOpen.type === "Refundable" ?
          <Badge tone="success">Refundable</Badge> :
          <Badge tone="danger">Non-refundable</Badge>}
          <span className="muted tiny">Conditions as contracted with the vendor</span>
        </div>
        {policyOpen.type === "Refundable" ?
        <table className="tbl">
          <thead><tr><th>Cancel before</th><th>Charge</th><th className="num">Refund</th></tr></thead>
          <tbody>
            {policyOpen.room && policyOpen.room.startsWith("Room") ?
            <>
              <tr><td>Up to Jul 9, 2026 · 23:59</td><td><Badge tone="success">Free cancellation</Badge></td><td className="num mono">100%</td></tr>
              <tr><td>Jul 10 – Jul 12, 2026</td><td>First night</td><td className="num mono">80%</td></tr>
              <tr><td>Jul 13 onwards / No-show</td><td>Full stay</td><td className="num mono">0%</td></tr>
            </> :
            <>
              <tr><td>More than 48 h before service</td><td><Badge tone="success">Free cancellation</Badge></td><td className="num mono">100%</td></tr>
              <tr><td>24 – 48 h before service</td><td>50% penalty</td><td className="num mono">50%</td></tr>
              <tr><td>Less than 24 h / No-show</td><td>Full charge</td><td className="num mono">0%</td></tr>
            </>}
          </tbody>
        </table> :
        <div style={{ background: "var(--danger-bg)", color: "var(--danger)", padding: "12px 14px", borderRadius: 8, fontSize: 13 }}>
          <div className="bold" style={{ marginBottom: 4 }}>Non-refundable {policyOpen.room && policyOpen.room.startsWith("Room") ? "rate" : "service"}</div>
          This {policyOpen.room && policyOpen.room.startsWith("Room") ? "room" : "service"} is non-refundable. Any cancellation or amendment incurs a <b>100% charge</b> of the total price. No refund applies for no-show or early termination.
        </div>}
        <div className="muted tiny" style={{ marginTop: 12 }}>Times shown in the service's local timezone. Penalties are deducted from the agency wallet on cancellation.</div>
      </Modal>}
    </div>);

}

function Step({ label, done, time, pending }) {
  return (
    <li style={{ display: "flex", alignItems: "flex-start", gap: 10, padding: "7px 0" }}>
      <span style={{
        width: 18, height: 18, borderRadius: 999,
        display: "grid", placeItems: "center", flexShrink: 0,
        background: done ? "var(--success)" : pending ? "transparent" : "var(--bg-subtle)",
        border: pending ? "1.5px dashed var(--border-strong)" : "none",
        color: "#fff"
      }}>
        {done && <Icon.Check size={11} stroke="#fff" />}
      </span>
      <div style={{ flex: 1 }}>
        <div style={{ color: done ? "var(--ink-1)" : "var(--ink-3)", fontWeight: done ? 500 : 400 }}>{label}</div>
        <div className="tiny muted">{time}</div>
      </div>
    </li>);

}

function PassengersTab({ b, editing }) {
  const code = b.type.code;
  // Group passengers by room / vehicle / unit so they're never mixed
  const groups = code === "hotel" ? [
  { unit: "Room 1 · Deluxe Sea-View", pax: [
    { name: "David García", type: "Adult", lead: true, nat: "Spain", doc: "DNI 42178890K", dob: "1986-04-12" },
    { name: "Laura García", type: "Adult", lead: false, nat: "Spain", doc: "DNI 42178891L", dob: "1988-09-03" }]
  },
  { unit: "Room 2 · Family Room", pax: [
    { name: "Mia García", type: "Child (8)", lead: false, nat: "Spain", doc: "Passport ES-X8841", dob: "2018-01-22" },
    { name: "Noah García", type: "Child (5)", lead: false, nat: "Spain", doc: "Passport ES-X8842", dob: "2021-03-10" }]
  }] :
  code === "car" ? [
  { unit: "Main driver", pax: [{ name: "David García", type: "Adult", lead: true, nat: "Spain", doc: "Licence ES-8841290", dob: "1986-04-12" }] },
  { unit: "Additional driver", pax: [{ name: "Laura García", type: "Adult", lead: false, nat: "Spain", doc: "Licence ES-8841291", dob: "1988-09-03" }] }] :
  code === "tr" ? [
  { unit: "Vehicle · Mercedes E-Class (3 pax)", pax: [
    { name: "David García", type: "Adult", lead: true, nat: "Spain", doc: "DNI 42178890K", dob: "1986-04-12" },
    { name: "Laura García", type: "Adult", lead: false, nat: "Spain", doc: "DNI 42178891L", dob: "1988-09-03" },
    { name: "Mia García", type: "Child (8)", lead: false, nat: "Spain", doc: "Passport ES-X8841", dob: "2018-01-22" }]
  }] :
  [
  { unit: "Service party (2 pax)", pax: [
    { name: "David García", type: "Adult", lead: true, nat: "Spain", doc: "DNI 42178890K", dob: "1986-04-12" },
    { name: "Laura García", type: "Adult", lead: false, nat: "Spain", doc: "DNI 42178891L", dob: "1988-09-03" }]
  }];

  const unitWord = code === "hotel" ? "room" : code === "car" ? "driver" : code === "tr" ? "vehicle" : "party";

  return (
    <div className="col" style={{ gap: 18 }}>
      <div className="row" style={{ gap: 8 }}>
        <span className="muted tiny">Passengers are grouped per {unitWord} so the right people are kept together. You can edit names; rooms / units cannot be added to an existing booking.</span>
      </div>
      {groups.map((g, gi) =>
      <Card key={gi} title={g.unit} sub={`${g.pax.filter((p) => p.type === "Adult").length} adult${g.pax.filter((p) => p.type === "Adult").length !== 1 ? "s" : ""} · ${g.pax.filter((p) => p.type.startsWith("Child")).length} child`} flush>
          <table className="tbl">
            <thead><tr><th>Name</th><th>Type</th><th>Nationality</th><th>Document</th><th>Date of birth</th></tr></thead>
            <tbody>
              {g.pax.map((p, i) =>
            <tr key={i}>
                  <td className="bold">{editing ? <input className="input" defaultValue={p.name} style={{ height: 30, maxWidth: 200 }} /> : <>{p.name} {p.lead && <Badge tone="indigo">Lead</Badge>}</>}</td>
                  <td>{p.type.startsWith("Child") ? <Badge tone="warning">{p.type}</Badge> : <Badge tone="neutral">{p.type}</Badge>}</td>
                  <td>{editing ? <input className="input" defaultValue={p.nat} style={{ height: 30, maxWidth: 140 }} /> : p.nat}</td>
                  <td className="mono">{editing ? <input className="input" defaultValue={p.doc} style={{ height: 30, maxWidth: 160 }} /> : p.doc}</td>
                  <td className="mono">{p.dob}</td>
                </tr>
            )}
            </tbody>
          </table>
          {editing && <div style={{ padding: "10px 14px" }}><Button kind="primary" size="sm" icon={<Icon.Check />} onClick={() => {
            var mainName = window.prompt("Main guest first name?", b.realDetail && b.realDetail.main_guest_name || "");
            if (mainName == null) return;
            var mainSurname = window.prompt("Main guest surname?", b.realDetail && b.realDetail.main_guest_surname || "");
            if (mainSurname == null) return;
            window.TrekkoAPI.savePassengerNames(b.shortId, { main_guest_name: mainName, main_guest_surname: mainSurname })
              .then(function (r) { toast({ title: "Passenger names saved", body: (r.changed && r.changed.main_guest_name) + " " + (r.changed && r.changed.main_guest_surname), tone: "success" }); })
              .catch(function (e) { toast({ title: "Save names failed", body: String(e && e.message || e), tone: "danger" }); });
          }}>Save names</Button></div>}
        </Card>
      )}
    </div>);

}

function LogTab() {
  const items = [
  { who: "System", what: "Booking confirmation email delivered to info@staytick.com", when: "10 min ago" },
  { who: "Maria Lopez", what: "Updated payment due date from Jul 25 to Aug 8", when: "2 hours ago" },
  { who: "Maria Lopez", what: "Marked payment status as Upcoming", when: "2 hours ago" },
  { who: "Juan Salazar", what: "Confirmed transfer category Economy ++", when: "Yesterday" },
  { who: "System", what: "Payment request #PR-44218 issued", when: "Yesterday" },
  { who: "Bailey Chen", what: "Created booking from API call (api.trekko.com)", when: "Jun 4, 2024 17:16" }];

  return (
    <Card title="Log history" flush>
      <ul style={{ listStyle: "none", margin: 0, padding: 0 }}>
        {items.map((i, n) =>
        <li key={n} style={{ display: "flex", gap: 12, padding: "14px 18px", borderBottom: "1px solid var(--border-hairline)" }}>
            <Avatar name={i.who} size="sm" />
            <div style={{ flex: 1 }}>
              <div><span className="bold">{i.who}</span> <span className="muted">{i.what}</span></div>
              <div className="tiny muted">{i.when}</div>
            </div>
          </li>
        )}
      </ul>
    </Card>);

}

function NotesTab() {
  const [val, setVal] = useState("");
  const [notes, setNotes] = useState([
  { who: "Maria Lopez", body: "Client requested a quieter pickup spot — confirmed with the vendor.", when: "2 hours ago" },
  { who: "Juan Salazar", body: "Carrier might be delayed if flight LH1408 arrives late. Watch ETA.", when: "Yesterday" }]
  );
  return (
    <Card title="Internal notes" sub="Visible to team members only">
      <div style={{ display: "flex", gap: 12, marginBottom: 16 }}>
        <Avatar name="Nabil Demo" />
        <div style={{ flex: 1 }}>
          <textarea className="textarea" placeholder="Write a note for the team…" value={val} onChange={(e) => setVal(e.target.value)} rows={3} />
          <div className="row" style={{ marginTop: 8, justifyContent: "flex-end" }}>
            <Button kind="ghost" size="sm" onClick={() => {
              var fileName = window.prompt("File name to attach (the file picker UI follows):");
              if (!fileName) return;
              // For now we audit-log the intent; real upload to S3 lands once
              // file-upload + presigned URLs are wired in.
              var bn = (window.location.pathname.match(/^\/bookings\/(.+)$/) || [])[1];
              if (!bn) { toast({ title: "Open a booking detail first", tone: "warning" }); return; }
              window.TrekkoAPI.attachNoteFile(bn, fileName)
                .then(function () { toast({ title: "Attachment queued", body: fileName + " (real S3 upload pending)", tone: "success" }); })
                .catch(function (e) { toast({ title: "Attach failed", body: String(e && e.message || e), tone: "danger" }); });
            }}>Attach file</Button>
            <Button kind="primary" size="sm" onClick={() => {if (val.trim()) {setNotes([{ who: "Nabil Demo", body: val, when: "Just now" }, ...notes]);setVal("");}}}>Post note</Button>
          </div>
        </div>
      </div>
      <ul style={{ listStyle: "none", margin: 0, padding: 0 }}>
        {notes.map((n, i) =>
        <li key={i} style={{ display: "flex", gap: 12, padding: "14px 0", borderTop: "1px solid var(--border-hairline)" }}>
            <Avatar name={n.who} size="sm" />
            <div style={{ flex: 1 }}>
              <div className="bold">{n.who} <span className="muted tiny" style={{ marginLeft: 6, fontWeight: 400 }}>{n.when}</span></div>
              <div style={{ marginTop: 2 }}>{n.body}</div>
            </div>
          </li>
        )}
      </ul>
    </Card>);

}

// ============================================================
// PAGE: PAYMENT MANAGEMENT (Bookings + Virtual Wallets)
// ============================================================
function PagePayments({ onOpenDetail }) {
  const [tab, setTab] = useState("bookings");
  return (
    <div>
      <div className="page-head">
        <div>
          <h1 className="page-head__title">Payment Management</h1>
          <div className="page-head__sub">Track receivables, top-ups and virtual wallet balances.</div>
        </div>
        <div className="page-head__actions">
          <Button kind="secondary" icon={<Icon.Download />} onClick={() => {
            window.TrekkoAPI.exportBookingsCsv(1000)
              .then(function () { toast({ title: "CSV downloaded", tone: "success" }); })
              .catch(function (e) { toast({ title: "Export failed", body: String(e && e.message || e), tone: "danger" }); });
          }}>Export</Button>
          <Button kind="primary" icon={<Icon.Plus />} onClick={() => {
            var bn = window.prompt("Booking number to issue an invoice for?");
            if (!bn) return;
            if (!window.TrekkoAPI || !window.TrekkoAPI.issueInvoice) { toast({ title: "Endpoint unavailable", tone: "danger" }); return; }
            window.TrekkoAPI.issueInvoice(bn)
              .then(function () { toast({ title: "Invoice queued for booking #" + bn, body: "Use Download Invoice to pull the PDF.", tone: "success" }); })
              .catch(function (e) { toast({ title: "Issue invoice failed", body: String(e && e.message || e), tone: "danger" }); });
          }}>Issue invoice</Button>
        </div>
      </div>

      <Tabs
        active={tab}
        onChange={setTab}
        tabs={[
        { id: "bookings", label: "Booking payments" },
        { id: "wallets", label: "Virtual wallets" },
        { id: "topups", label: "Top-up transactions" }]
        } />
      

      {tab === "bookings" && <PageBookings onOpenDetail={onOpenDetail} />}

      {tab === "wallets" && <WalletsView />}
      {tab === "topups" && <TopUpsView />}
    </div>);

}

function WalletsView() {
  const { useState, useEffect, useMemo } = React;
  const [adjust, setAdjust] = useState(null);
  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 walletKpis = useMemo(() => {
    let prepaidWallets = 0, prepaidCount = 0, depositsHeld = 0, creditCount = 0, lowBalance = 0;
    agencies.forEach((a) => {
      if (a.payType === "Prepaid") { prepaidWallets += a.wallet || 0; prepaidCount += 1; if ((a.wallet || 0) < 500) lowBalance += 1; }
      else if (a.payType === "Credit") { depositsHeld += a.deposit || 0; creditCount += 1; }
    });
    return { prepaidWallets, prepaidCount, depositsHeld, creditCount, lowBalance };
  }, [agencies]);
  return (
    <>
      <div className="grid grid--4" style={{ marginBottom: 18 }}>
        <Metric accent label="Virtual wallets (prepaid)" value={"€" + walletKpis.prepaidWallets.toLocaleString()} hint={"Across " + walletKpis.prepaidCount + " prepaid agencies"} />
        <Metric label="Deposits held (credit)" value={"€" + walletKpis.depositsHeld.toLocaleString()} hint={"From " + walletKpis.creditCount + " credit agencies"} />
        <Metric label="Low balance alerts" value={String(walletKpis.lowBalance)} hint="Prepaid wallets below €500" />
        <Metric label="Pending top-ups" value="—" hint="Awaiting backend feed" />
      </div>
      <div className="row" style={{ gap: 10, marginBottom: 14, background: "var(--info-bg)", padding: "10px 12px", borderRadius: 8, color: "var(--info)" }}>
        <Icon.Info stroke="currentColor" />
        <div style={{ fontSize: 13 }}>A <b>virtual wallet</b> belongs to <b>prepaid</b> agencies (spendable balance). A <b>deposit</b> is held from <b>credit</b> agencies (we double it as their limit). <b>Full Credit</b> agencies hold neither.</div>
      </div>

      <div className="filter-bar">
        <input className="input input--search" placeholder="Search by agency name…" style={{ width: 280 }} />
        <select className="select"><option>All balance ranges</option><option>Below €500</option><option>€500 — €2,000</option><option>€2,000+</option></select>
        <span className="spacer" />
        <Button kind="secondary" icon={<Icon.Plus />} onClick={() => setAdjust({ name: "", id: "", bal: 0 })}>Adjust balance</Button>
      </div>

      <div className="tbl-wrap tbl-wrap--linked">
        <table className="tbl">
          <thead>
            <tr>
              <th>Agency</th>
              <th>Type</th>
              <th className="num">Wallet / Deposit</th>
              <th className="num">Credit used</th>
              <th className="num">Available</th>
              <th>Last activity</th>
              <th>Status</th>
              <th className="col-actions"></th>
            </tr>
          </thead>
          <tbody>
            {agencies.map((a, i) => {
              const isPrepaid = a.payType === "Prepaid";
              const isCredit = a.payType === "Credit";
              const bal = isPrepaid ? (a.wallet || 0) : isCredit ? a.deposit : 0;
              const avail = isPrepaid ? bal : a.payType === "Full Credit" ? (a.creditLimit - a.creditUsed) : (a.creditLimit - a.creditUsed);
              const low = isPrepaid && bal < 500;
              return (
                <tr key={a.id}>
                  <td>
                    <span className="user-cell"><Avatar name={a.name} size="sm" /><span><div className="bold">{a.name}</div><div className="tiny muted">{a.id}</div></span></span>
                  </td>
                  <td>{a.payType === "Full Credit" ? <Badge tone="indigo">Full Credit</Badge> : isCredit ? <Badge tone="warning">Credit</Badge> : <Badge tone="neutral">Prepaid</Badge>}</td>
                  <td className="num mono bold">{a.payType === "Full Credit" ? <span className="muted">—</span> : <>€{bal.toLocaleString()} <span className="tiny muted">{isPrepaid ? "wallet" : "deposit"}</span></>}</td>
                  <td className="num mono muted">{isPrepaid ? "—" : "€" + a.creditUsed.toLocaleString()}</td>
                  <td className="num mono">€{avail.toLocaleString()}</td>
                  <td className="mono">{["2 hr ago", "Yesterday", "3 days", "1 week", "2 weeks", "Today", "Today", "5 days", "Yesterday", "Today"][i] || "—"}</td>
                  <td>{low ? <Badge tone="warning">Low — top up</Badge> : a.payType === "Full Credit" ? <Badge tone="indigo">No deposit</Badge> : <Badge tone="success">Healthy</Badge>}</td>
                  <td className="col-actions">
                    <Button kind="secondary" size="sm" onClick={() => setAdjust({ name: a.name, id: a.id, bal })}>Adjust</Button>
                  </td>
                </tr>);

            })}
          </tbody>
        </table>
      </div>
      <Pager page={1} pageSize={10} total={248} onPage={() => {}} />

      {adjust &&
      <Modal open title={`Adjust wallet${adjust.name ? " · " + adjust.name : ""}`} onClose={() => setAdjust(null)}
        footer={<><Button kind="ghost" onClick={() => setAdjust(null)}>Cancel</Button>
                <Button kind="primary" icon={<Icon.Check />} onClick={async () => { try { const sel = document.querySelector(".modal select"); const inp = document.querySelector(".modal input[type=number]"); const op = sel ? sel.value : "topup"; const amt = inp ? parseFloat(inp.value) || 0 : 0; const delta = op === "deduct" ? -Math.abs(amt) : op === "set" ? amt - (adjust.bal || 0) : op === "refund" ? -(adjust.bal || 0) : Math.abs(amt); if (delta !== 0 && window.TrekkoAPI && adjust.id) await window.TrekkoAPI.adjustWallet(adjust.id, delta, op === "refund" ? "refund" : "manual_adjustment", ""); toast({ title: "Wallet updated", body: adjust.name, tone: "success" }); } catch (e) { toast({ title: "Save failed", body: e.message, tone: "danger" }); } finally { setAdjust(null); } }}>Save</Button></>}>
        {adjust.name && <div className="row" style={{ gap: 8, marginBottom: 14, padding: "10px 12px", background: "var(--bg-subtle)", borderRadius: 8 }}>
          <Avatar name={adjust.name} size="sm" />
          <div><div className="bold">{adjust.name}</div><div className="tiny muted">Current balance €{adjust.bal.toLocaleString()}</div></div>
        </div>}
        <Field label="Operation">
          <select className="select" defaultValue="topup">
            <option value="topup">Top up (add funds)</option>
            <option value="deduct">Deduct (remove funds)</option>
            <option value="refund">Refund all — return full balance to agency</option>
            <option value="set">Set exact balance</option>
          </select>
        </Field>
        <div style={{ height: 12 }} />
        <Field label="Amount (€)" hint="For 'Refund all', the full available balance is returned and the wallet is set to €0.">
          <input className="input" type="number" defaultValue={adjust.bal} placeholder="0.00" />
        </Field>
        <div style={{ height: 12 }} />
        <div className="grid grid--2" style={{ gap: 12 }}>
          <Field label="Method"><select className="select"><option>Bank transfer (SEPA)</option><option>Card refund</option><option>Manual adjustment</option></select></Field>
          <Field label="Reference"><input className="input" placeholder="REF / invoice no." /></Field>
        </div>
        <div style={{ height: 12 }} />
        <Field label="Reason / note"><textarea className="textarea" placeholder="e.g. Agency requested full wallet refund on account closure" /></Field>
      </Modal>}
    </>);

}

function TopUpsView() {
  const [detail, setDetail] = useState(null);
  const { useState: useStateTU, useEffect: useEffectTU, useMemo: useMemoTU } = React;
  const [rows, setRows] = useStateTU((window.MOCK && window.MOCK.TOPUPS) || []);
  useEffectTU(() => {
    if (!window.TrekkoAPI) return;
    window.TrekkoAPI.getTopUps().then((data) => { if (data && data.length) setRows(data); });
  }, []);
  const tuKpis = useMemoTU(() => {
    const today = new Date().toISOString().slice(0, 10);
    const todays = rows.filter((r) => String(r.date).startsWith(today));
    const total = rows.reduce((s, r) => s + (Number(r.amount) || 0), 0);
    const successes = rows.filter((r) => /success|paid/i.test(String(r.status))).length;
    const failed24 = rows.filter((r) => /failed|cancelled/i.test(String(r.status))).length;
    return {
      today: todays.reduce((s, r) => s + (Number(r.amount) || 0), 0),
      todayCount: todays.length,
      successRate: rows.length ? (successes / rows.length * 100).toFixed(1) + "%" : "-",
      failed24,
      avg: rows.length ? "€" + Math.round(total / rows.length).toLocaleString() : "-",
    };
  }, [rows]);
  return (
    <>
      <div className="grid grid--4" style={{ marginBottom: 18 }}>
        <Metric accent label="Top-ups today" value={"€" + tuKpis.today.toLocaleString()} hint={tuKpis.todayCount + " transactions"} />
        <Metric label="Success rate" value={tuKpis.successRate} />
        <Metric label="Failed last 24h" value={String(tuKpis.failed24)} />
        <Metric label="Average top-up" value={tuKpis.avg} hint="Across loaded transactions" />
      </div>

      <div className="filter-bar">
        <input className="input input--search" placeholder="Search by transaction ID, agency or reference…" style={{ width: 320 }} />
        <select className="select"><option>All methods</option><option>Card</option><option>Bank Transfer</option><option>Wallet</option></select>
        <select className="select"><option>All statuses</option><option>Success</option><option>Pending</option><option>Failed</option></select>
        <span className="spacer" />
        <Button kind="secondary" icon={<Icon.Download />} onClick={() => {
          window.TrekkoAPI.exportTopupsCsv()
            .then(function () { toast({ title: "Top-ups CSV downloaded", body: "WalletsTransactionsTable backing pending.", tone: "info" }); })
            .catch(function (e) { toast({ title: "Export failed", body: String(e && e.message || e), tone: "danger" }); });
        }}>Export</Button>
      </div>

      <div className="tbl-wrap tbl-wrap--linked">
        <table className="tbl">
          <thead>
            <tr>
              <th>Transaction</th><th>Agency</th><th>Method</th><th className="num">Amount</th><th className="num">Fee</th><th>Reference</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"><a href="#" onClick={(e) => {e.preventDefault();setDetail(t);}}>{t.id}</a></td>
                <td className="bold">{t.agency}</td>
                <td>
                  <span className="row" style={{ gap: 6 }}>
                    {t.method === "Card" && <Icon.Payment size={14} />}
                    {t.method === "Bank Transfer" && <Icon.Building size={14} />}
                    {t.method === "Wallet" && <Icon.Wallet size={14} />}
                    {t.method}
                  </span>
                </td>
                <td className="num mono bold">€{t.amount.toLocaleString()}</td>
                <td className="num mono muted">€{t.fee}</td>
                <td className="mono muted">{t.ref}</td>
                <td className="mono">{t.date}</td>
                <td><StatusBadge status={t.status} /></td>
                <td className="col-actions">
                  <Button kind="secondary" size="sm" onClick={() => setDetail(t)}>View</Button>
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
      <Pager page={1} pageSize={10} total={rows.length} onPage={() => {}} />

      <TopUpDetailModal tx={detail} onClose={() => setDetail(null)} />
    </>);

}

function TopUpDetailModal({ tx, onClose }) {
  if (!tx) return null;
  return (
    <Modal
      open
      onClose={onClose}
      title={`Transaction ${tx.id}`}
      size="lg"
      footer={<>
        <Button kind="secondary" onClick={onClose}>Close</Button>
        {tx.status === "Pending" && <Button kind="success" icon={<Icon.Check />} onClick={() => {
          window.TrekkoAPI.transactionAction(tx.id, "confirm")
            .then(function () { toast({ title: "Confirm queued", body: tx.id, tone: "success" }); })
            .catch(function (e) { toast({ title: "Confirm failed", body: String(e && e.message || e), tone: "danger" }); });
        }}>Confirm</Button>}
        {tx.status === "Failed" && <Button kind="primary" icon={<Icon.Refresh />} onClick={() => {
          window.TrekkoAPI.transactionAction(tx.id, "retry")
            .then(function () { toast({ title: "Retry queued", body: tx.id, tone: "success" }); })
            .catch(function (e) { toast({ title: "Retry failed", body: String(e && e.message || e), tone: "danger" }); });
        }}>Retry</Button>}
        <Button kind="secondary" icon={<Icon.Download />} onClick={() => {
          var invNo = tx.invoiceId || tx.id;
          if (!invNo) { toast({ title: "No invoice id on this tx", tone: "warning" }); return; }
          window.TrekkoAPI.downloadBookingInvoice(String(invNo).replace(/^INV-/, ""))
            .then(function () { toast({ title: "Receipt downloaded", tone: "success" }); })
            .catch(function (e) { toast({ title: "Receipt download failed", body: String(e && e.message || e), tone: "danger" }); });
        }}>Receipt</Button>
      </>}>
      
      <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 16 }}>
        <div>
          <div className="muted tiny">Status</div>
          <div style={{ marginTop: 6 }}><StatusBadge status={tx.status} /></div>
          <div style={{ height: 14 }} />
          <div className="muted tiny">Amount</div>
          <div style={{ fontSize: 28, fontWeight: 700, letterSpacing: "-0.02em" }}>€{tx.amount.toLocaleString()}</div>
          <div className="muted tiny">Net €{(tx.amount - tx.fee).toLocaleString()} after €{tx.fee} fee</div>
        </div>
        <div>
          <dl className="dl">
            <dt>Agency</dt><dd className="bold">{tx.agency}</dd>
            <dt>Method</dt><dd>{tx.method}</dd>
            <dt>Reference</dt><dd className="mono">{tx.ref}</dd>
            <dt>Date</dt><dd className="mono">{tx.date}</dd>
            <dt>Processor</dt><dd>{tx.method === "Card" ? "Stripe Connect" : tx.method === "Bank Transfer" ? "SEPA via Bankinter" : "Trekko Wallet"}</dd>
            <dt>Country</dt><dd>Spain</dd>
          </dl>
        </div>
      </div>
      <div style={{ height: 16 }} />
      <Card title="Timeline" flush>
        <ul style={{ listStyle: "none", margin: 0, padding: 0 }}>
          <Step label="Top-up initiated" done time={tx.date} />
          <Step label={tx.method === "Card" ? "Card authorised" : "Sender verified"} done={tx.status !== "Failed"} time={tx.date} />
          <Step label="Funds settled to wallet" done={tx.status === "Success"} time={tx.status === "Success" ? "Today" : "—"} pending={tx.status === "Pending"} />
        </ul>
      </Card>
    </Modal>);

}

Object.assign(window, { PageBookings, PageBookingDetail, PagePayments, StatusBadge, WalletsView, TopUpsView });
