// csr-queue.jsx — bookings summary: filters (status / type / state), cancel, update, resend tracking link
const { useState: useStateQ, useEffect: useEffectQ } = React;

// SLA window (hours after ready time) by service tier
function slaHours(b) {
  if (b.typeId === "nextflight") return 8;
  if (b.serviceId === "direct") return 1.5;
  if (b.serviceId === "premium") return 3;
  return 6;
}
function dueInfo(b, now) {
  let due;
  if (b.dueAt) { due = new Date(b.dueAt); }
  else {
    if (!b.date || !b.time || !/^\d{2}:\d{2}$/.test(b.time)) return null;
    due = new Date(b.date + "T" + b.time + ":00");
    if (isNaN(due)) return null;
    due.setMinutes(due.getMinutes() + Math.round(slaHours(b) * 60));
  }
  if (isNaN(due)) return null;
  const clock = due.toLocaleTimeString("en-AU", { hour: "2-digit", minute: "2-digit" });
  const msLeft = due.getTime() - now;
  const tone = msLeft < 0 ? "danger" : msLeft < 60 * 60000 ? "warn" : "success";
  return { due, clock, msLeft, tone };
}
function fmtLeft(ms) {
  const late = ms < 0;
  let m = Math.round(Math.abs(ms) / 60000);
  const d = Math.floor(m / 1440); m -= d * 1440;
  const h = Math.floor(m / 60); const mm = m % 60;
  const core = d > 0 ? `${d}d ${h}h` : h > 0 ? `${h}h ${mm}m` : `${mm}m`;
  return late ? core + " late" : core + " left";
}
function importantCustomer(b) {
  const c = window.FX.CUSTOMERS.find(x => x.ref === b.customerRef || x.id === b.customerId);
  return (c && c.priority) || b.typeId === "failsafe-critical";
}

function BookingsQueue({ bookings, currency, onEdit, onCancel, onNew, onNotify }) {
  const [q, setQ] = useStateQ("");
  const [view, setView] = useStateQ("all");
  const [statusF, setStatusF] = useStateQ("active");
  const [typeF, setTypeF] = useStateQ("all");
  const [stateF, setStateF] = useStateQ("all");
  const [confirmCancel, setConfirmCancel] = useStateQ(null);
  const [resend, setResend] = useStateQ(null);
  const [nowTs, setNowTs] = useStateQ(Date.now());
  useEffectQ(() => { const id = setInterval(() => setNowTs(Date.now()), 1000); return () => clearInterval(id); }, []);
  function openBooking(b) { window.location.href = "Fedex Booking.html#t=" + encodeURIComponent(b.tracking); }

  const stateOf = b => b.state || window.FX.suburbState(b.dropoff.suburb) || "—";
  const isActive = b => b.status !== "Cancelled" && b.status !== "Delivered";
  const isLate = b => { const d = dueInfo(b, nowTs); return isActive(b) && d && d.msLeft < 60 * 60000; };
  const lateCount = bookings.filter(isLate).length;
  const importantCount = bookings.filter(b => b.status !== "Cancelled" && importantCustomer(b)).length;
  const nfCount = bookings.filter(b => b.status !== "Cancelled" && b.status !== "Delivered" && window.FX.isNextFlight(b)).length;
  const ql = q.trim().toLowerCase();
  let filtered = bookings.filter(b => {
    if (view === "late" && !isLate(b)) return false;
    if (view === "important" && !(b.status !== "Cancelled" && importantCustomer(b))) return false;
    if (view === "nextflight" && !window.FX.isNextFlight(b)) return false;
    if (statusF === "active" && b.status === "Cancelled") return false;
    if (statusF !== "active" && statusF !== "all" && b.status !== statusF) return false;
    if (typeF !== "all" && b.typeId !== typeF) return false;
    if (stateF !== "all" && stateOf(b) !== stateF) return false;
    if (ql && !(b.tracking + b.customerName + b.customerRef + b.pickup.suburb + b.dropoff.suburb).toLowerCase().includes(ql)) return false;
    return true;
  });
  if (view === "late") {
    filtered = [...filtered].sort((a, b) => { const da = dueInfo(a, nowTs), db = dueInfo(b, nowTs); return (da ? da.msLeft : 1e15) - (db ? db.msLeft : 1e15); });
  }

  const typeOf = id => window.FX.BOOKING_TYPES.find(t => t.id === id);
  const statusTone = s => s === "Cancelled" ? "danger" : s === "In transit" ? "brand" : "success";
  const statusDot = s => s === "Cancelled" ? "var(--danger)" : s === "In transit" ? "var(--brand)" : "var(--success)";

  const GRID = "0.9fr 1.02fr 1fr 0.7fr 0.92fr 0.86fr 0.76fr 104px";
  const selStyle = { width: "auto", minWidth: 0, paddingTop: 9, paddingBottom: 9, fontSize: 13.5 };

  return (
    <div className="fade-up">
      {/* tabs */}
      <div style={{ display: "flex", gap: 6, marginBottom: 16, borderBottom: "1px solid var(--border)" }}>
        {[["all", "All bookings", null], ["late", "Late / at risk", lateCount], ["important", "Important customers", importantCount], ["nextflight", "Next Flight", nfCount]].map(([k, lbl, count]) => {
          const on = view === k;
          const danger = k === "late" && count > 0;
          return (
            <button key={k} onClick={() => setView(k)} style={{ display: "inline-flex", alignItems: "center", gap: 8, padding: "11px 16px", border: "none", background: "transparent", borderBottom: "2px solid " + (on ? "var(--brand)" : "transparent"), color: on ? "var(--brand)" : "var(--fg-mute)", fontSize: 14, fontWeight: on ? 700 : 500, marginBottom: -1 }}>
              {k === "late" && <Icon name="clock" size={15} color={danger ? "var(--danger)" : "currentColor"} />}
              {k === "important" && <Icon name="star" size={15} />}
              {k === "nextflight" && <Icon name="plane" size={15} />}
              {lbl}
              {count != null && count > 0 && <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, fontWeight: 600, padding: "1px 7px", borderRadius: 999, background: danger ? "var(--danger)" : on ? "var(--brand)" : "var(--bg-mist-2)", color: danger || on ? "#fff" : "var(--fg-mute)" }}>{count}</span>}
            </button>
          );
        })}
      </div>

      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 14, marginBottom: 18, flexWrap: "wrap" }}>
        <div style={{ display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 6, color: "var(--fg-mute)", fontSize: 12.5, fontWeight: 500, marginRight: 2 }}><Icon name="filter" size={15} /> Filter</span>
          <Select value={statusF} onChange={setStatusF} style={selStyle} options={[{ value: "active", label: "Active" }, { value: "Booked", label: "Booked" }, { value: "In transit", label: "In transit" }, { value: "Cancelled", label: "Cancelled" }, { value: "all", label: "All statuses" }]} />
          <Select value={typeF} onChange={setTypeF} style={selStyle} options={[{ value: "all", label: "All types" }, ...window.FX.BOOKING_TYPES.map(t => ({ value: t.id, label: t.short }))]} />
          <Select value={stateF} onChange={setStateF} style={selStyle} options={[{ value: "all", label: "All states" }, ...window.FX.STATES.map(s => ({ value: s, label: s }))]} />
        </div>
        <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
          <div style={{ position: "relative" }}>
            <span style={{ position: "absolute", left: 12, top: "50%", transform: "translateY(-50%)", color: "var(--fg-mute)" }}><Icon name="search" size={15} /></span>
            <TextInput value={q} onChange={setQ} placeholder="Search bookings…" style={{ paddingLeft: 36, width: 220 }} />
          </div>
          <Button variant="primary" icon="plus" onClick={onNew}>New booking</Button>
        </div>
      </div>

      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 12, fontSize: 13, color: "var(--fg-mute)" }}>
        <strong style={{ color: "var(--fg-strong)" }}>{filtered.length}</strong> booking{filtered.length === 1 ? "" : "s"}
        {(statusF !== "active" || typeF !== "all" || stateF !== "all" || ql) && <button onClick={() => { setStatusF("active"); setTypeF("all"); setStateF("all"); setQ(""); }} style={{ background: "transparent", border: "none", color: "var(--accent-700)", fontSize: 12.5, fontWeight: 500, display: "inline-flex", alignItems: "center", gap: 4 }}><Icon name="x" size={12} /> Clear filters</button>}
      </div>

      <Card pad={0} style={{ overflow: "hidden" }}>
        <div style={{ display: "grid", gridTemplateColumns: GRID, gap: 10, padding: "12px 20px", background: "var(--bg-mist)", borderBottom: "1px solid var(--border)", fontFamily: "var(--font-mono)", fontSize: 10.5, letterSpacing: "0.8px", textTransform: "uppercase", color: "var(--fg-mute)" }}>
          <span>Tracking</span><span>Customer</span><span>Route</span><span>Type</span><span>Driver</span><span>Due</span><span>Status</span><span style={{ textAlign: "right" }}>Actions</span>
        </div>
        {filtered.map((b, i) => {
          const t = typeOf(b.typeId);
          const cancelled = b.status === "Cancelled";
          return (
            <div key={b.tracking + i} onClick={() => openBooking(b)} style={{ display: "grid", gridTemplateColumns: GRID, gap: 10, padding: "14px 20px", borderTop: i ? "1px solid var(--border)" : "none", alignItems: "center", opacity: cancelled ? 0.55 : 1, cursor: "pointer", transition: "background 120ms ease" }}
              onMouseEnter={e => e.currentTarget.style.background = "var(--bg-mist)"} onMouseLeave={e => e.currentTarget.style.background = "transparent"}>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 12.5, fontWeight: 600, color: "var(--brand)" }}>{b.tracking}</span>
              <span style={{ minWidth: 0 }}>
                <span style={{ display: "block", fontSize: 13.5, fontWeight: 500, color: "var(--fg-strong)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{b.customerName}</span>
                <span style={{ display: "block", fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--fg-mute)" }}>{b.customerRef}</span>
              </span>
              <span style={{ fontSize: 13, color: "var(--fg-body)", minWidth: 0, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{b.pickup.suburb} <Icon name="arrow-right" size={11} color="var(--fg-faint)" style={{ verticalAlign: "middle" }} /> {b.dropoff.suburb}{b.isReturn ? <span style={{ color: "var(--accent-700)" }}> ↩</span> : ""}{b.stops && b.stops.length > 2 ? <span style={{ color: "var(--fg-faint)" }}> +{b.stops.length - 2}</span> : ""}</span>
              <span style={{ minWidth: 0 }}>
                <span><Badge tone={t ? t.tone : "neutral"}>{t ? t.short : b.typeId}</Badge>{importantCustomer(b) && <Icon name="star" size={12} color="var(--accent)" style={{ marginLeft: 5, verticalAlign: "middle" }} />}</span>
                {window.FX.isNextFlight(b) && <span style={{ display: "flex", alignItems: "center", gap: 4, fontFamily: "var(--font-mono)", fontSize: 11, fontWeight: 600, color: "var(--brand)", marginTop: 4 }}><Icon name="plane" size={11} /> {window.FX.nextFlightInfo(b).flightIata}</span>}
              </span>
              <span style={{ minWidth: 0 }}>
                {b.driver ? (
                  <span style={{ display: "flex", alignItems: "center", gap: 8, minWidth: 0 }}>
                    <span style={{ width: 26, height: 26, borderRadius: "50%", flex: "none", background: "var(--brand)", color: "#fff", display: "inline-flex", alignItems: "center", justifyContent: "center", fontWeight: 700, fontSize: 10.5 }}>{b.driver.initials}</span>
                    <span style={{ minWidth: 0 }}>
                      <span style={{ display: "block", fontSize: 12.5, fontWeight: 500, color: "var(--fg-strong)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{b.driver.name}</span>
                      <span style={{ display: "block", fontFamily: "var(--font-mono)", fontSize: 10.5, color: "var(--fg-mute)" }}>{b.driver.rego}</span>
                    </span>
                  </span>
                ) : <span style={{ fontSize: 12, color: "var(--fg-faint)", fontStyle: "italic" }}>Unassigned</span>}
              </span>
              <span style={{ minWidth: 0 }}>{(() => {
                const di = dueInfo(b, nowTs);
                if (!di) return <span style={{ fontSize: 12.5, color: "var(--fg-faint)" }}>—</span>;
                const delivered = b.status === "Delivered", cx = b.status === "Cancelled";
                return (
                  <span>
                    <span style={{ display: "block", fontFamily: "var(--font-mono)", fontSize: 12.5, fontWeight: 600, color: "var(--fg-strong)" }}>{di.clock}</span>
                    {delivered ? <span style={{ fontSize: 11, color: "#108a52", fontWeight: 600 }}>Delivered</span>
                      : cx ? <span style={{ fontSize: 11, color: "var(--fg-faint)" }}>—</span>
                      : <span style={{ display: "inline-block", fontFamily: "var(--font-mono)", fontSize: 10.5, fontWeight: 600, marginTop: 2, padding: "1px 7px", borderRadius: 999, background: di.tone === "danger" ? "var(--danger-soft)" : di.tone === "warn" ? "var(--warn-soft)" : "var(--success-soft)", color: di.tone === "danger" ? "var(--danger)" : di.tone === "warn" ? "#a36a00" : "#108a52" }}>{fmtLeft(di.msLeft)}</span>}
                  </span>
                );
              })()}</span>
              <span><Badge tone={statusTone(b.status)}><StatusDot color={statusDot(b.status)} pulse={b.status === "In transit"} /> {b.status}</Badge></span>
              <span style={{ display: "flex", gap: 5, justifyContent: "flex-end" }} onClick={e => e.stopPropagation()}>
                {!cancelled && <>
                  <button onClick={() => setResend(b)} title="Resend tracking link" style={{ background: "var(--brand-soft)", border: "none", borderRadius: 8, width: 30, height: 30, display: "inline-flex", alignItems: "center", justifyContent: "center", color: "var(--brand)" }}><Icon name="send" size={14} /></button>
                  <button onClick={() => onEdit(b)} title="Update booking" style={{ background: "var(--bg-mist)", border: "none", borderRadius: 8, width: 30, height: 30, display: "inline-flex", alignItems: "center", justifyContent: "center", color: "var(--fg-body)" }}><Icon name="pen-tool" size={14} /></button>
                  <button onClick={() => setConfirmCancel(b)} title="Cancel booking" style={{ background: "var(--danger-soft)", border: "none", borderRadius: 8, width: 30, height: 30, display: "inline-flex", alignItems: "center", justifyContent: "center", color: "var(--danger)" }}><Icon name="x" size={15} /></button>
                </>}
                {cancelled && <span style={{ fontSize: 12, color: "var(--fg-faint)", fontStyle: "italic" }}>Cancelled</span>}
              </span>
            </div>
          );
        })}
        {filtered.length === 0 && (
          <div style={{ padding: 48, textAlign: "center" }}>
            <div style={{ width: 52, height: 52, borderRadius: "50%", background: "var(--bg-mist)", display: "inline-flex", alignItems: "center", justifyContent: "center", margin: "0 auto 12px", color: "var(--fg-faint)" }}><Icon name="package" size={24} /></div>
            <div style={{ fontSize: 14.5, fontWeight: 600, color: "var(--fg-strong)" }}>No bookings match these filters</div>
            <div style={{ fontSize: 13, color: "var(--fg-mute)", marginTop: 4 }}>Adjust the filters above, or take a new booking.</div>
          </div>
        )}
      </Card>

      <Modal open={!!confirmCancel} onClose={() => setConfirmCancel(null)} title="Cancel booking?" width={440}>
        {confirmCancel && (
          <div>
            <div style={{ display: "flex", alignItems: "center", gap: 12, padding: 14, background: "var(--danger-soft)", borderRadius: "var(--r-md)", marginBottom: 16 }}>
              <Icon name="info" size={20} color="var(--danger)" />
              <div style={{ fontSize: 13.5, color: "var(--fg-strong)" }}>Booking <span className="mono" style={{ fontWeight: 600 }}>{confirmCancel.tracking}</span> for <strong>{confirmCancel.customerName}</strong> will be cancelled. This can't be undone.</div>
            </div>
            <div style={{ display: "flex", gap: 10 }}>
              <Button variant="ghost" full onClick={() => setConfirmCancel(null)}>Keep booking</Button>
              <Button variant="primary" full icon="x" onClick={() => { onCancel(confirmCancel); setConfirmCancel(null); }} style={{ background: "var(--danger)" }}>Cancel booking</Button>
            </div>
          </div>
        )}
      </Modal>

      <ResendModal booking={resend} onClose={() => setResend(null)} onSent={(msg) => { setResend(null); onNotify && onNotify(msg); }} />
    </div>
  );
}

/* Resend tracking link — SMS and/or email, to existing or a new number/address */
function ResendModal({ booking, onClose, onSent }) {
  const dropoff = booking ? booking.dropoff : {};
  const [smsOn, setSmsOn] = useStateQ(true);
  const [emailOn, setEmailOn] = useStateQ(false);
  const [smsMode, setSmsMode] = useStateQ("existing");
  const [emailMode, setEmailMode] = useStateQ("existing");
  const [newPhone, setNewPhone] = useStateQ("");
  const [newEmail, setNewEmail] = useStateQ("");

  React.useEffect(() => {
    if (booking) {
      setSmsOn(true); setEmailOn(false); setSmsMode(dropoff.phone ? "existing" : "new"); setEmailMode(dropoff.email ? "existing" : "new"); setNewPhone(""); setNewEmail("");
    }
  }, [booking]);
  if (!booking) return null;

  const link = "track.fedex.com.au/t/" + booking.tracking.replace(/^FX-/, "");
  const smsTarget = smsMode === "existing" ? dropoff.phone : newPhone;
  const emailTarget = emailMode === "existing" ? dropoff.email : newEmail;
  const canSend = (smsOn && smsTarget) || (emailOn && emailTarget);

  function send() {
    const parts = [];
    if (smsOn && smsTarget) parts.push("SMS to " + smsTarget);
    if (emailOn && emailTarget) parts.push("email to " + emailTarget);
    onSent(`Tracking link sent · ${parts.join(" & ")}`);
  }

  const renderChannel = ({ on, setOn, icon, title, mode, setMode, existing, newVal, setNew, placeholder, type }) => (
    <div style={{ border: "1.5px solid " + (on ? "var(--brand)" : "var(--border)"), borderRadius: "var(--r-md)", padding: 14, transition: "all 140ms ease", background: on ? "var(--surface)" : "var(--bg-mist)" }}>
      <button onClick={() => setOn(!on)} style={{ display: "flex", alignItems: "center", gap: 10, width: "100%", background: "transparent", border: "none", textAlign: "left", padding: 0 }}>
        <span style={{ width: 32, height: 32, borderRadius: 9, flex: "none", display: "inline-flex", alignItems: "center", justifyContent: "center", background: on ? "var(--brand)" : "var(--bg-mist-2)", color: on ? "#fff" : "var(--fg-mute)" }}><Icon name={icon} size={16} /></span>
        <span style={{ flex: 1, fontWeight: 600, fontSize: 14.5, color: "var(--fg-strong)" }}>{title}</span>
        <span style={{ width: 38, height: 22, borderRadius: 999, flex: "none", background: on ? "var(--brand)" : "var(--bg-mist-2)", position: "relative", transition: "all 160ms ease" }}>
          <span style={{ position: "absolute", top: 2, left: on ? 18 : 2, width: 18, height: 18, borderRadius: "50%", background: "#fff", transition: "all 160ms ease", boxShadow: "var(--shadow-xs)" }} />
        </span>
      </button>
      {on && (
        <div style={{ marginTop: 12, display: "flex", flexDirection: "column", gap: 9 }}>
          {existing && (
            <button onClick={() => setMode("existing")} style={{ display: "flex", alignItems: "center", gap: 9, background: "transparent", border: "none", padding: 0, textAlign: "left" }}>
              <Radio on={mode === "existing"} />
              <span style={{ fontSize: 13.5, color: "var(--fg-body)" }}>Existing · <span className="mono" style={{ color: "var(--fg-strong)" }}>{existing}</span></span>
            </button>
          )}
          <button onClick={() => setMode("new")} style={{ display: "flex", alignItems: "center", gap: 9, background: "transparent", border: "none", padding: 0, textAlign: "left" }}>
            <Radio on={mode === "new"} /><span style={{ fontSize: 13.5, color: "var(--fg-body)" }}>Send to a new {type === "tel" ? "number" : "address"}</span>
          </button>
          {mode === "new" && <TextInput value={newVal} onChange={setNew} placeholder={placeholder} mono={type === "tel"} />}
        </div>
      )}
    </div>
  );

  return (
    <Modal open={!!booking} onClose={onClose} title="Resend tracking link" width={520}>
      <div style={{ display: "flex", alignItems: "center", gap: 11, padding: 13, background: "var(--brand-soft)", borderRadius: "var(--r-md)", marginBottom: 16 }}>
        <Icon name="link" size={17} color="var(--brand)" />
        <div style={{ minWidth: 0 }}>
          <div style={{ fontSize: 12, color: "var(--fg-mute)" }}>Tracking link for <span className="mono" style={{ fontWeight: 600, color: "var(--brand)" }}>{booking.tracking}</span></div>
          <div style={{ fontFamily: "var(--font-mono)", fontSize: 13, color: "var(--fg-strong)", marginTop: 2 }}>{link}</div>
        </div>
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 11 }}>
        {renderChannel({ on: smsOn, setOn: setSmsOn, icon: "message-square", title: "Send by SMS", mode: smsMode, setMode: setSmsMode, existing: dropoff.phone, newVal: newPhone, setNew: setNewPhone, placeholder: "+61 4xx xxx xxx", type: "tel" })}
        {renderChannel({ on: emailOn, setOn: setEmailOn, icon: "mail", title: "Send by email", mode: emailMode, setMode: setEmailMode, existing: dropoff.email, newVal: newEmail, setNew: setNewEmail, placeholder: "name@company.com.au", type: "email" })}
      </div>
      <div style={{ display: "flex", gap: 10, marginTop: 18 }}>
        <Button variant="ghost" onClick={onClose}>Cancel</Button>
        <Button variant="primary" full icon="send" onClick={send} disabled={!canSend}>Send tracking link</Button>
      </div>
    </Modal>
  );
}
function Radio({ on }) {
  return (
    <span style={{ width: 18, height: 18, borderRadius: "50%", flex: "none", border: "2px solid " + (on ? "var(--brand)" : "var(--border-strong)"), display: "inline-flex", alignItems: "center", justifyContent: "center" }}>
      {on && <span style={{ width: 8, height: 8, borderRadius: "50%", background: "var(--brand)" }} />}
    </span>
  );
}

/* Live driver-location map (schematic) */
function DriverMap({ booking }) {
  const p = Math.max(0, Math.min(1, booking.progress || 0));
  const delivered = booking.status === "Delivered";
  const pts = [[60,200],[150,170],[230,130],[320,110],[420,72],[520,44]];
  const idx = Math.min(pts.length - 2, Math.floor(p * (pts.length - 1)));
  const f = p * (pts.length - 1) - idx;
  const dx = pts[idx][0] + (pts[idx+1][0] - pts[idx][0]) * f;
  const dy = pts[idx][1] + (pts[idx+1][1] - pts[idx][1]) * f;
  return (
    <div style={{ position: "relative", height: 230, borderRadius: "var(--r-lg)", overflow: "hidden", background: "#0B2240", border: "1px solid var(--border)" }}>
      <svg width="100%" height="100%" style={{ position: "absolute", inset: 0, opacity: 0.2 }}>
        <defs><pattern id="csrgrid" width="34" height="34" patternUnits="userSpaceOnUse"><path d="M34 0 L0 0 0 34" fill="none" stroke="rgba(120,160,220,0.6)" strokeWidth="0.5" /></pattern></defs>
        <rect width="100%" height="100%" fill="url(#csrgrid)" />
      </svg>
      <svg width="100%" height="100%" viewBox="0 0 580 230" preserveAspectRatio="none" style={{ position: "absolute", inset: 0 }}>
        <path d="M 60 200 C 150 170 320 150 420 72 C 470 44 500 44 520 44" stroke="rgba(255,255,255,0.25)" strokeWidth="3.5" fill="none" strokeDasharray="2 7" strokeLinecap="round" />
        <path d="M 60 200 C 150 170 320 150 420 72 C 470 44 500 44 520 44" stroke="var(--accent)" strokeWidth="3.5" fill="none" strokeLinecap="round" strokeDasharray="700" strokeDashoffset={700 - 700 * p} />
      </svg>
      <Pin x="60" y="200" color="var(--brand)" label={booking.pickup.suburb} />
      <Pin x="520" y="44" color="#fff" ring="var(--accent)" label={booking.dropoff.suburb} />
      {!delivered && booking.driver && (
        <div style={{ position: "absolute", left: `${dx/580*100}%`, top: `${dy/230*100}%`, transform: "translate(-50%,-50%)" }}>
          <span style={{ width: 34, height: 34, borderRadius: "50%", background: "#fff", display: "inline-flex", alignItems: "center", justifyContent: "center", boxShadow: "0 4px 12px rgba(0,0,0,0.4)", animation: "pulseDot 1.8s infinite" }}>
            <Icon name="navigation" size={17} color="var(--brand)" />
          </span>
        </div>
      )}
      {delivered && <div style={{ position: "absolute", top: 12, left: 12 }}><Badge tone="success" style={{ background: "#fff" }}><StatusDot color="#22b86e" /> Delivered</Badge></div>}
      {!delivered && booking.driver && (
        <div style={{ position: "absolute", left: 12, bottom: 12, right: 12, display: "flex", justifyContent: "space-between", alignItems: "flex-end", gap: 10 }}>
          <div style={{ background: "#fff", borderRadius: 12, padding: "9px 13px", boxShadow: "var(--shadow-toast)", display: "flex", alignItems: "center", gap: 10 }}>
            <span style={{ width: 32, height: 32, borderRadius: "50%", background: "var(--brand)", color: "#fff", display: "inline-flex", alignItems: "center", justifyContent: "center", fontWeight: 700, fontSize: 12 }}>{booking.driver.initials}</span>
            <div><div style={{ fontWeight: 600, fontSize: 13, color: "var(--fg-strong)" }}>{booking.driver.name}</div><div style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--fg-mute)" }}>{booking.driver.vehicle} · {booking.driver.rego}</div></div>
          </div>
          <div style={{ background: "var(--accent)", color: "#fff", borderRadius: 12, padding: "9px 13px", boxShadow: "var(--shadow-toast)", textAlign: "right" }}>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, letterSpacing: "1px", opacity: 0.85 }}>EN ROUTE</div>
            <div style={{ fontWeight: 800, fontSize: 16 }}>{Math.round(p * 100)}%</div>
          </div>
        </div>
      )}
    </div>
  );
}
function Pin({ x, y, color, ring, label }) {
  return (
    <div style={{ position: "absolute", left: `${x/580*100}%`, top: `${y/230*100}%`, transform: "translate(-50%,-50%)", display: "flex", flexDirection: "column", alignItems: "center", gap: 4 }}>
      <span style={{ width: 14, height: 14, borderRadius: "50%", background: color, border: `3px solid ${ring || "#fff"}`, boxShadow: "0 3px 8px rgba(0,0,0,0.4)" }} />
      <span style={{ fontSize: 10.5, fontWeight: 600, color: "#fff", background: "rgba(1,16,31,0.6)", padding: "2px 7px", borderRadius: 6, whiteSpace: "nowrap" }}>{label}</span>
    </div>
  );
}

/* Booking detail / summary */
function BookingDetail({ booking, currency, onClose, onEdit, onResend, onCancel }) {
  if (!booking) return null;
  const b = booking;
  const type = window.FX.BOOKING_TYPES.find(x => x.id === b.typeId);
  const size = window.FX.VEHICLES.find(x => x.id === b.vehicleId);
  const svc = window.FX.SERVICES.find(x => x.id === b.serviceId);
  const cancelled = b.status === "Cancelled";
  const inTransit = b.status === "In transit";
  const chargesTotal = (b.charges || []).reduce((s, c) => s + c.amount * (c.qty || 1), 0);
  const link = "track.fedex.com.au/t/" + b.tracking.replace(/^FX-/, "");
  const Row = ({ label, children, top }) => (
    <div style={{ display: "flex", justifyContent: "space-between", gap: 14, padding: "9px 0", borderTop: top ? "none" : "1px solid var(--border)" }}>
      <span style={{ fontSize: 12.5, color: "var(--fg-mute)", flex: "none" }}>{label}</span>
      <span style={{ fontSize: 13, color: "var(--fg-strong)", fontWeight: 500, textAlign: "right" }}>{children}</span>
    </div>
  );
  const statusTone = b.status === "Cancelled" ? "danger" : b.status === "In transit" ? "brand" : b.status === "Delivered" ? "neutral" : "success";
  const statusCol = b.status === "Cancelled" ? "var(--danger)" : b.status === "In transit" ? "var(--brand)" : b.status === "Delivered" ? "var(--fg-mute)" : "var(--success)";
  return (
    <Modal open={!!booking} onClose={onClose} title="Booking summary" width={760}>
      {/* header */}
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 16, flexWrap: "wrap" }}>
        <span style={{ fontFamily: "var(--font-mono)", fontSize: 17, fontWeight: 700, color: "var(--brand)" }}>{b.tracking}</span>
        <Badge tone={type ? type.tone : "neutral"}>{type ? type.name : b.typeId}</Badge>
        <Badge tone={statusTone}><StatusDot color={statusCol} pulse={inTransit} /> {b.status}</Badge>
        <span style={{ marginLeft: "auto", fontSize: 20, fontWeight: 900, letterSpacing: "-0.5px", color: "var(--fg-strong)" }}>{window.FX.money(b.total, currency)}</span>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1.25fr 1fr", gap: 18, alignItems: "start" }}>
        {/* left: map + route */}
        <div>
          {(inTransit || b.status === "Delivered") ? <DriverMap booking={b} /> : (
            <div style={{ height: 230, borderRadius: "var(--r-lg)", border: "1px dashed var(--border-strong)", background: "var(--bg-mist)", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 8, color: "var(--fg-mute)" }}>
              <Icon name="navigation" size={26} color="var(--fg-faint)" />
              <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--fg-strong)" }}>{cancelled ? "Booking cancelled" : "Awaiting pickup"}</div>
              <div style={{ fontSize: 12.5 }}>{cancelled ? "No live tracking" : "Live tracking starts once the driver collects"}</div>
            </div>
          )}
          {/* tracking link */}
          <div style={{ display: "flex", alignItems: "center", gap: 10, marginTop: 12, padding: "10px 13px", background: "var(--brand-soft)", borderRadius: "var(--r-md)" }}>
            <Icon name="link" size={15} color="var(--brand)" />
            <span style={{ flex: 1, fontFamily: "var(--font-mono)", fontSize: 12.5, color: "var(--brand)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{link}</span>
            {!cancelled && <button onClick={() => onResend(b)} style={{ display: "inline-flex", alignItems: "center", gap: 5, background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 7, padding: "5px 10px", fontSize: 12, fontWeight: 500, color: "var(--fg-body)" }}><Icon name="send" size={12} /> Resend</button>}
          </div>
          {/* full route */}
          <div style={{ marginTop: 14 }}>
            <Stop accent="var(--brand)" label="Pickup" addr={b.pickup} time={`${window.FX.fmtDate(b.date)} · ${b.time || "—"}`} />
            <div style={{ width: 2, height: 14, background: "var(--border-strong)", margin: "2px 0 2px 12px" }} />
            <Stop accent="var(--accent)" label="Deliver to" addr={b.dropoff} />
          </div>
        </div>

        {/* right: details */}
        <div>
          {/* driver card */}
          <div style={{ border: "1px solid var(--border)", borderRadius: "var(--r-md)", padding: 13, marginBottom: 14 }}>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.8px", textTransform: "uppercase", color: "var(--fg-mute)", marginBottom: 9 }}>Driver</div>
            {b.driver ? (
              <div style={{ display: "flex", alignItems: "center", gap: 11 }}>
                <span style={{ width: 40, height: 40, borderRadius: "50%", background: "var(--brand)", color: "#fff", display: "inline-flex", alignItems: "center", justifyContent: "center", fontWeight: 700, fontSize: 14, flex: "none" }}>{b.driver.initials}</span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 14, fontWeight: 600, color: "var(--fg-strong)" }}>{b.driver.name}</div>
                  <div style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--fg-mute)" }}>{b.driver.vehicle} · {b.driver.rego}</div>
                </div>
                <a href={"tel:" + b.driver.phone} onClick={e => e.stopPropagation()} style={{ width: 34, height: 34, borderRadius: "50%", background: "var(--brand-soft)", color: "var(--brand)", display: "inline-flex", alignItems: "center", justifyContent: "center", flex: "none" }}><Icon name="phone" size={16} /></a>
              </div>
            ) : <div style={{ fontSize: 13, color: "var(--fg-mute)", fontStyle: "italic" }}>Not yet assigned — awaiting dispatch.</div>}
          </div>

          <Row label="Customer" top>{b.customerName}</Row>
          <Row label="Reference">{b.customerRef}{b.ref1 ? " · " + b.ref1 : ""}</Row>
          <Row label="Size">{size ? size.name : "—"}</Row>
          <Row label="Service">{svc ? svc.name : "—"}{size && svc ? " · " + window.FX.serviceCode(svc.id, size.id) : ""}</Row>
          <Row label="Distance">{b.km != null ? b.km + " km" : "—"}</Row>
          <Row label="Return trip">{b.isReturn ? "Yes" : "No"}</Row>
          {(b.charges || []).map((c, i) => <Row key={i} label={i === 0 ? "Charges" : ""}>{c.label}{c.qty > 1 ? " ×" + c.qty : ""} · {window.FX.money(c.amount * (c.qty || 1), currency)}</Row>)}
          <Row label="Total (incl GST)"><strong>{window.FX.money(b.total, currency)}</strong></Row>
        </div>
      </div>

      {/* type instructions */}
      {type && (
        <div style={{ marginTop: 16, padding: "13px 15px", borderRadius: "var(--r-md)", background: "var(--brand)", color: "#fff" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }}>
            <Icon name="info" size={15} /><span style={{ fontFamily: "var(--font-mono)", fontSize: 10.5, letterSpacing: "1px", textTransform: "uppercase", opacity: 0.85 }}>Special instructions · {type.short}</span>
          </div>
          <ul style={{ margin: 0, paddingLeft: 18, display: "flex", flexDirection: "column", gap: 4 }}>
            {type.instructions.map((ins, i) => <li key={i} style={{ fontSize: 12.5, lineHeight: 1.4 }}>{ins}</li>)}
          </ul>
        </div>
      )}
      {b.notes && <div style={{ marginTop: 12, padding: "11px 14px", background: "var(--bg-mist)", borderRadius: "var(--r-md)", fontSize: 13, color: "var(--fg-body)" }}><strong style={{ color: "var(--fg-strong)" }}>Notes: </strong>{b.notes}</div>}

      {!cancelled && (
        <div style={{ display: "flex", gap: 10, marginTop: 18 }}>
          <Button variant="secondary" icon="pen-tool" onClick={() => onEdit(b)}>Update booking</Button>
          <Button variant="ghost" icon="send" onClick={() => onResend(b)}>Resend link</Button>
          <Button variant="ghost" icon="x" onClick={() => onCancel(b)} style={{ marginLeft: "auto", color: "var(--danger)" }}>Cancel booking</Button>
        </div>
      )}
    </Modal>
  );
}
function Stop({ accent, label, addr, time }) {
  return (
    <div style={{ display: "flex", gap: 11 }}>
      <span style={{ width: 26, height: 26, borderRadius: 8, background: accent, color: "#fff", display: "inline-flex", alignItems: "center", justifyContent: "center", flex: "none" }}><Icon name="map-pin" size={14} /></span>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.6px", textTransform: "uppercase", color: "var(--fg-mute)" }}>{label}{time ? " · " + time : ""}</div>
        <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--fg-strong)", marginTop: 2 }}>{addr.company || addr.contact}</div>
        <div style={{ fontSize: 12.5, color: "var(--fg-body)" }}>{addr.unit ? addr.unit + ", " : ""}{addr.line ? addr.line + ", " : ""}{addr.suburb}{addr.postcode ? " " + addr.postcode : ""}</div>
        {addr.contact && <div style={{ fontSize: 12, color: "var(--fg-mute)", marginTop: 2 }}>{addr.contact}{addr.phone ? " · " + addr.phone : ""}</div>}
        {addr.instructions && <div style={{ fontSize: 12, color: "var(--fg-body)", marginTop: 4, fontStyle: "italic", borderLeft: "2px solid var(--accent)", paddingLeft: 7 }}>{addr.instructions}</div>}
      </div>
    </div>
  );
}

Object.assign(window, { BookingsQueue });
