// Driver view — desktop panel + mobile (iOS frame) modes
const { useState: useStateDriver, useEffect: useEffectDriver, useRef: useRefDriver, useMemo: useMemoDriver } = React;

// Last-mile delivery fee paid to the Nigeria driver, in local NGN
const lastMilePayout = (job) => Math.round((job.price || 0) * 75 / 500) * 500;

// === Reusable: status timeline (vertical), slide-to-confirm, OTP collector ===

const FlowSteps = ({ current, history }) => {
  const steps = STATUS_ORDER;
  const idx = steps.indexOf(current);
  return (
    <div className="timeline">
      {steps.map((s, i) => {
        const cls = i < idx ? "done" : i === idx ? "current" : "upcoming";
        const ev = history.find(e => e.k === s);
        return (
          <div key={s} className={"timeline-row " + cls}>
            <span className="timeline-bullet" />
            <span className="timeline-line" />
            <div className="timeline-content">
              <div className="timeline-name">{statusLabel(s)}</div>
              <div className="timeline-meta">{ev ? `${ev.t} · ${ev.text}` : (i === idx ? "Tap the action below" : "—")}</div>
            </div>
          </div>
        );
      })}
    </div>
  );
};

const SlideToConfirm = ({ label, onConfirm, color = "var(--accent)" }) => {
  const [dx, setDx] = useStateDriver(0);
  const ref = useRefDriver(null);
  const startX = useRefDriver(0);
  const dragging = useRefDriver(false);

  const onDown = (e) => {
    dragging.current = true;
    const px = e.touches ? e.touches[0].clientX : e.clientX;
    startX.current = px - dx;
  };
  const onMove = (e) => {
    if (!dragging.current) return;
    const px = e.touches ? e.touches[0].clientX : e.clientX;
    const max = (ref.current?.offsetWidth || 300) - 50;
    const v = Math.max(0, Math.min(max, px - startX.current));
    setDx(v);
  };
  const onUp = () => {
    if (!dragging.current) return;
    dragging.current = false;
    const max = (ref.current?.offsetWidth || 300) - 50;
    if (dx > max * 0.75) {
      setDx(max);
      setTimeout(() => { onConfirm(); setDx(0); }, 200);
    } else {
      setDx(0);
    }
  };

  useEffectDriver(() => {
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseup", onUp);
    window.addEventListener("touchmove", onMove);
    window.addEventListener("touchend", onUp);
    return () => {
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseup", onUp);
      window.removeEventListener("touchmove", onMove);
      window.removeEventListener("touchend", onUp);
    };
  });

  return (
    <div className="slide-confirm" ref={ref}>
      <span className="fill" style={{ width: dx + 44 + 3 }} />
      <span className="track-label" style={{ opacity: Math.max(0, 1 - dx / 100) }}>{label}</span>
      <span
        className="knob"
        style={{ transform: `translateX(${dx}px)`, background: color }}
        onMouseDown={onDown}
        onTouchStart={onDown}
      >
        <FFIcon name="chev" size={18} stroke={2.4} />
      </span>
    </div>
  );
};

const TwoTapConfirm = ({ label, onConfirm }) => {
  const [armed, setArmed] = useStateDriver(false);
  useEffectDriver(() => {
    if (!armed) return;
    const t = setTimeout(() => setArmed(false), 3000);
    return () => clearTimeout(t);
  }, [armed]);
  return (
    <button
      className={"btn " + (armed ? "btn-danger" : "btn-primary")}
      style={{ width: "100%", justifyContent: "center", padding: 14, fontSize: 14 }}
      onClick={() => armed ? onConfirm() : setArmed(true)}
    >
      {armed ? "Tap again to confirm" : label}
    </button>
  );
};

const ConfirmAction = ({ variant, label, onConfirm }) => {
  if (variant === "slide") return <SlideToConfirm label={label} onConfirm={onConfirm} />;
  if (variant === "two-tap") return <TwoTapConfirm label={label} onConfirm={onConfirm} />;
  return (
    <button className="btn btn-primary" style={{ width: "100%", justifyContent: "center", padding: 14, fontSize: 14 }} onClick={onConfirm}>
      {label}
    </button>
  );
};

// OTP entry: numpad (driver types after SMS) or split-boxes (recipient types directly)
const OTPNumpad = ({ value, setValue, onSubmit, length = 6 }) => {
  const press = (k) => {
    if (k === "<") setValue(value.slice(0, -1));
    else if (k === "✓") onSubmit();
    else if (value.length < length) setValue(value + k);
  };
  return (
    <>
      <div className="otp-boxes">
        {Array.from({ length }).map((_, i) => (
          <div key={i} className={"otp-box" + (i < value.length ? " filled" : (i === value.length ? " cursor" : ""))}>
            {value[i] || ""}
          </div>
        ))}
      </div>
      <div className="numpad">
        {["1","2","3","4","5","6","7","8","9"].map(n =>
          <button key={n} onClick={() => press(n)}>{n}</button>
        )}
        <button className="clear" onClick={() => press("<")}><FFIcon name="backspace" size={18} /></button>
        <button onClick={() => press("0")}>0</button>
        <button className="submit" onClick={() => press("✓")} disabled={value.length !== length}><FFIcon name="check" size={18} stroke={2.4} /></button>
      </div>
    </>
  );
};

// === Job card content (shared by desktop & mobile) ===

const JobBody = ({ job, statusVariant, otpVariant, confirmVariant, onAdvance, onComplete, sendMessage }) => {
  const [otp, setOtp] = useStateDriver("");
  const [otpRequested, setOtpRequested] = useStateDriver(!!job.otpDelivered);
  const [error, setError] = useStateDriver("");

  // Reset OTP state when job changes
  useEffectDriver(() => { setOtp(""); setOtpRequested(!!job.otpDelivered); setError(""); }, [job.id]);

  const requestOTP = () => {
    if (!job.otp) return;
    sendMessage({
      channel: "sms",
      to: job.delivery.phone,
      subject: "Delivery OTP",
      body: `Your Folfem delivery OTP for ${job.id} is ${job.otp}. Share with the driver to confirm receipt.`,
      jobId: job.id,
    });
    setOtpRequested(true);
  };

  const submitOTP = () => {
    if (otp === job.otp) {
      onComplete(job.id);
      setError("");
    } else {
      setError("Code doesn't match. Please re-enter.");
      setOtp("");
    }
  };

  // ---- Map / layout-first variant chooser ----
  const showMapFirst = statusVariant === "map-first";
  const compact = statusVariant === "list-compact";

  const routeBlock = (
    <div className="dm-card">
      <h4>Last-mile route</h4>
      <div className="dm-route">
        <div className="rail">
          <span className="pin" />
          <span className="line" />
          <span className="pin dest" />
        </div>
        <div className="stops">
          <div className="stop">
            <div className="l">Collect from hub</div>
            <div className="addr">{job.hub.name}</div>
            <div className="sub">{job.hub.addr}</div>
          </div>
          <div className="stop">
            <div className="l">Deliver to · {job.delivery.time}</div>
            <div className="addr">{job.delivery.name}</div>
            <div className="sub">{job.delivery.addr}</div>
            <div className="sub mono" style={{ marginTop: 2 }}>{job.delivery.phone}</div>
          </div>
        </div>
      </div>
      <div className="origin-note"><FFIcon name={modeIcon(job.mode)} size={12} />Arrived from {job.origin.name}, UK · {job.service}</div>
    </div>
  );

  const cargoBlock = (
    <div className="dm-card">
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
        <h4 style={{ margin: 0 }}>Shipment</h4>
        <ModeBadge mode={job.mode} service={job.service} />
      </div>
      <div style={{ fontWeight: 600, fontSize: 13, marginTop: 8 }}>{job.service}</div>
      <div style={{ color: "var(--muted)", fontSize: 12, marginTop: 4 }}>{job.contents}</div>
      <div style={{ marginTop: 10, display: "flex", justifyContent: "space-between" }}>
        <div>
          <div style={{ fontSize: 10, color: "var(--muted)", textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 700 }}>Sender</div>
          <div className="mono" style={{ fontWeight: 700, fontSize: 14 }}>🇬🇧 {job.client.split(" ")[0]}</div>
        </div>
        <div style={{ textAlign: "right" }}>
          <div style={{ fontSize: 10, color: "var(--muted)", textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 700 }}>Your payout</div>
          <div className="mono" style={{ fontWeight: 700, fontSize: 14 }}>{formatNGN(lastMilePayout(job))}</div>
        </div>
      </div>
    </div>
  );

  const mapBlock = (
    <div className="dm-map">
      <span className="map-label">map: {job.hub.addr} → {job.delivery.addr.split(",").slice(-2)[0].trim()}</span>
    </div>
  );

  // ---- Action block by status ----
  let actionBlock = null;

  if (job.status === "Assigned") {
    actionBlock = (
      <>
        <div style={{ fontSize: 12, color: "var(--muted)", marginBottom: 10, textAlign: "center" }}>
          Dispatcher has assigned this job to you. Accept to begin.
        </div>
        <ConfirmAction variant={confirmVariant} label="Accept job" onConfirm={() => onAdvance(job.id, "Accepted", "Driver accepted the job")} />
        <button className="btn btn-ghost" style={{ width: "100%", justifyContent: "center", marginTop: 8, color: "var(--red-ink)" }}>Decline</button>
      </>
    );
  } else if (job.status === "Accepted") {
    actionBlock = (
      <>
        <div style={{ fontSize: 12, color: "var(--muted)", marginBottom: 10, textAlign: "center" }}>
          Once loaded at the hub, mark as out for delivery.
        </div>
        <ConfirmAction variant={confirmVariant} label="Out for delivery" onConfirm={() => onAdvance(job.id, "InTransit", "Collected from hub, out for delivery")} />
      </>
    );
  } else if (job.status === "InTransit") {
    // OTP flow
    if (otpVariant === "recipient-types") {
      // Hand phone to recipient
      actionBlock = (
        <div>
          <div style={{ fontSize: 12, color: "var(--muted)", textAlign: "center", marginBottom: 4 }}>
            Hand the phone to <strong style={{ color: "var(--ink)" }}>{job.delivery.contact}</strong>
          </div>
          <div style={{ fontSize: 11, color: "var(--muted)", textAlign: "center", marginBottom: 10 }}>
            They received the code by SMS from Folfem.
          </div>
          <div className="dm-card" style={{ padding: 12 }}>
            <OTPNumpad value={otp} setValue={setOtp} onSubmit={submitOTP} />
            {error && <div style={{ color: "var(--red-ink)", fontSize: 12, textAlign: "center", marginTop: 8 }}>{error}</div>}
          </div>
        </div>
      );
    } else {
      // Driver requests OTP, recipient SMSes it back, driver types
      if (!otpRequested) {
        actionBlock = (
          <>
            <div style={{ fontSize: 12, color: "var(--muted)", marginBottom: 10, textAlign: "center" }}>
              Tap to send the proof-of-delivery OTP to <strong style={{ color: "var(--ink)" }}>{job.delivery.contact}</strong> at {job.delivery.phone}.
            </div>
            <ConfirmAction variant={confirmVariant} label="Send OTP & confirm arrival" onConfirm={requestOTP} />
          </>
        );
      } else {
        actionBlock = (
          <div>
            <div style={{ fontSize: 12, color: "var(--accent-ink)", textAlign: "center", marginBottom: 4, display: "flex", gap: 6, alignItems: "center", justifyContent: "center" }}>
              <FFIcon name="sms" size={14} />OTP sent to recipient
            </div>
            <div style={{ fontSize: 11, color: "var(--muted)", textAlign: "center", marginBottom: 10 }}>
              Ask <strong style={{ color: "var(--ink)" }}>{job.delivery.contact}</strong> for the 6-digit code.
            </div>
            <div className="dm-card" style={{ padding: 12 }}>
              <OTPNumpad value={otp} setValue={setOtp} onSubmit={submitOTP} />
              {error && <div style={{ color: "var(--red-ink)", fontSize: 12, textAlign: "center", marginTop: 8 }}>{error}</div>}
              <button className="btn btn-ghost" style={{ width: "100%", justifyContent: "center", marginTop: 8, fontSize: 12 }} onClick={requestOTP}>Resend OTP</button>
            </div>
          </div>
        );
      }
    }
  } else if (job.status === "Delivered") {
    actionBlock = (
      <div style={{ textAlign: "center", padding: "10px 0" }}>
        <div style={{ width: 48, height: 48, borderRadius: 24, background: "var(--accent-soft)", color: "var(--accent-ink)", display: "grid", placeItems: "center", margin: "0 auto 10px" }}>
          <FFIcon name="check" size={22} stroke={2.5} />
        </div>
        <div style={{ fontWeight: 700, fontSize: 14 }}>Delivered</div>
        <div style={{ fontSize: 12, color: "var(--muted)", marginTop: 2 }}>{formatNGN(lastMilePayout(job))} added to your earnings</div>
      </div>
    );
  } else {
    actionBlock = <div style={{ color: "var(--muted)", textAlign: "center", fontSize: 12 }}>Waiting on dispatch…</div>;
  }

  return { mapBlock, routeBlock, cargoBlock, actionBlock };
};

// === Desktop driver view ===

const DriverDesktop = ({ jobs, driver, statusVariant, otpVariant, confirmVariant, advance, complete, sendMessage }) => {
  const myJobs = jobs.filter(j => j.driverId === driver.id);
  const activeFirst = [...myJobs].sort((a, b) => STATUS_ORDER.indexOf(b.status) - STATUS_ORDER.indexOf(a.status) || 0);
  const [selectedId, setSelectedId] = useStateDriver(activeFirst.find(j => j.status !== "Delivered")?.id || activeFirst[0]?.id);
  useEffectDriver(() => {
    if (!myJobs.find(j => j.id === selectedId) && myJobs[0]) setSelectedId(myJobs[0].id);
  }, [myJobs.length]);

  const selected = myJobs.find(j => j.id === selectedId);
  if (!selected) {
    return (
      <div className="driver-desktop">
        <div style={{ padding: 40, color: "var(--muted)" }}>No jobs assigned to {driver.name}.</div>
      </div>
    );
  }
  const { mapBlock, routeBlock, cargoBlock, actionBlock } = JobBody({
    job: selected, statusVariant, otpVariant, confirmVariant,
    onAdvance: advance, onComplete: complete, sendMessage,
  });

  return (
    <div className="driver-desktop">
      <aside className="dd-list">
        <div className="dd-list-head">
          <h2>My jobs</h2>
          <p>{myJobs.length} total · {myJobs.filter(j => j.status !== "Delivered").length} active</p>
        </div>
        <div className="dd-jobs">
          {activeFirst.map(j => (
            <button key={j.id} className={selectedId === j.id ? "active" : ""} onClick={() => setSelectedId(j.id)}>
              <div className="top">
                <span className="jid">{j.id}</span>
                <span className={"chip status-" + j.status} style={{ fontSize: 10, padding: "2px 6px" }}><span className="chip-dot" />{statusLabel(j.status)}</span>
              </div>
              <div className="route">{j.hub.name} <span>→</span> {j.delivery.name}</div>
              <div className="sub">{j.service} · {formatNGN(lastMilePayout(j))}</div>
            </button>
          ))}
        </div>
      </aside>

      <div className="dd-detail">
        <div className="dd-hero">
          <span className="avatar xl">{initials(driver.name)}</span>
          <div>
            <h2>{selected.id} · {selected.service}</h2>
            <div className="sub">{selected.client} · collect from {selected.hub.name}</div>
          </div>
          <div className="actions">
            <button className="btn"><FFIcon name="phone" size={14} />Call recipient</button>
            <button className="btn"><FFIcon name="map" size={14} />Open in maps</button>
          </div>
        </div>

        <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 1.4fr) minmax(0, 1fr)", gap: 16 }}>
          <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
            <div className="dm-card" style={{ padding: 0 }}>
              <div style={{ padding: "14px 16px 10px" }}><h4 style={{ margin: 0, fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--muted)" }}>Live map</h4></div>
              <div style={{ padding: "0 14px 14px" }}>
                <MapPlaceholder height={180} label={`${selected.hub.addr} → ${selected.delivery.addr.split(",").slice(-2)[0].trim()}`} pins={[{ x: 18, y: 70 }, { x: 78, y: 22, kind: "dest" }, { x: 45, y: 50 }]} />
              </div>
            </div>
            {routeBlock}
            {cargoBlock}
          </div>

          <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
            <div className="dm-card">
              <h4>Progress</h4>
              <FlowSteps current={selected.status} history={selected.events} />
            </div>
            <div className="dm-card">
              <h4>{selected.status === "InTransit" ? "Proof of delivery" : "Next action"}</h4>
              <div style={{ marginTop: 8 }}>{actionBlock}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

// === Driver wallet (earnings + withdraw) ===

const DriverWallet = ({ jobs, driver, onBack, pushToast }) => {
  const delivered = jobs.filter(j => j.driverId === driver.id && j.status === "Delivered");

  // Prior payouts already cashed out (seeded history)
  const [history, setHistory] = useStateDriver([
    { id: "WD-2207", amount: 95000, date: "31 May", bank: "GTBank ••4471", status: "Paid" },
    { id: "WD-2186", amount: 60000, date: "24 May", bank: "GTBank ••4471", status: "Paid" },
  ]);
  // Delivered jobs that have already been withdrawn (none initially → all available)
  const [cashedJobIds, setCashedJobIds] = useStateDriver([]);

  const availableJobs = delivered.filter(j => !cashedJobIds.includes(j.id));
  const available = availableJobs.reduce((s, j) => s + lastMilePayout(j), 0);
  const withdrawn = history.reduce((s, w) => s + w.amount, 0);
  const lifetime = delivered.reduce((s, j) => s + lastMilePayout(j), 0) + withdrawn;

  const [sheet, setSheet] = useStateDriver(false); // false | "form" | "done"

  const confirmWithdraw = () => {
    const ref = "WD-" + Math.floor(2300 + Math.random() * 99);
    setHistory(h => [
      { id: ref, amount: available, date: "Today", bank: "GTBank ••4471", status: "Processing" },
      ...h,
    ]);
    setCashedJobIds(delivered.map(j => j.id));
    pushToast && pushToast({ title: "Withdrawal started", desc: `${formatNGN(available)} → GTBank ••4471` });
    setSheet("done");
  };

  return (
    <div className="dm">
      <div className="dm-head">
        <button className="menu" onClick={onBack} style={{ border: 0, cursor: "pointer" }}>
          <FFIcon name="chev" size={16} stroke={2.4} style={{ transform: "rotate(180deg)" }} />
        </button>
        <div className="who" style={{ marginLeft: 6 }}>
          <div className="nm">Wallet</div>
          <div style={{ fontSize: 11, color: "var(--muted)" }}>{driver.name.split(" ")[0]} · {driver.city}</div>
        </div>
        <span className="avatar av">{initials(driver.name)}</span>
      </div>

      <div className="dm-body">
        <div className="wallet-hero">
          <div className="wh-label">Available to withdraw</div>
          <div className="wh-balance">{formatNGN(available)}</div>
          <div className="wh-sub">{availableJobs.length} deliver{availableJobs.length === 1 ? "y" : "ies"} ready to cash out</div>
          <button
            className="wh-btn"
            disabled={available === 0}
            onClick={() => setSheet("form")}
          >
            <FFIcon name="arrowUp" size={16} stroke={2.2} />Withdraw to bank
          </button>
        </div>

        <div className="wallet-stats">
          <div className="wallet-stat">
            <div className="ws-val">{formatNGN(lifetime)}</div>
            <div className="ws-lbl">Lifetime earned</div>
          </div>
          <div className="wallet-stat">
            <div className="ws-val">{delivered.length}</div>
            <div className="ws-lbl">Deliveries</div>
          </div>
        </div>

        <div className="dm-card" style={{ padding: 0 }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "14px 14px 6px" }}>
            <h4 style={{ margin: 0 }}>Earnings from deliveries</h4>
          </div>
          {delivered.length === 0 && (
            <div style={{ padding: "0 14px 14px", color: "var(--muted)", fontSize: 12 }}>No completed deliveries yet.</div>
          )}
          {delivered.map(j => {
            const cashed = cashedJobIds.includes(j.id);
            return (
              <div key={j.id} className="wallet-row">
                <span className="wr-icon"><FFIcon name="box" size={15} /></span>
                <div className="wr-main">
                  <div className="wr-title">{j.delivery.name}</div>
                  <div className="wr-sub mono">{j.id} · {j.events.find(e => e.k === "Delivered")?.t || ""}</div>
                </div>
                <div className="wr-amt">
                  <div className="mono" style={{ fontWeight: 700 }}>+{formatNGN(lastMilePayout(j))}</div>
                  <div className={"wr-state " + (cashed ? "paid" : "ready")}>{cashed ? "Withdrawn" : "Available"}</div>
                </div>
              </div>
            );
          })}
        </div>

        <div className="dm-card" style={{ padding: 0 }}>
          <div style={{ padding: "14px 14px 6px" }}><h4 style={{ margin: 0 }}>Withdrawal history</h4></div>
          {history.map(w => (
            <div key={w.id} className="wallet-row">
              <span className="wr-icon out"><FFIcon name="bank" size={15} /></span>
              <div className="wr-main">
                <div className="wr-title">{w.bank}</div>
                <div className="wr-sub mono">{w.id} · {w.date}</div>
              </div>
              <div className="wr-amt">
                <div className="mono" style={{ fontWeight: 700 }}>−{formatNGN(w.amount)}</div>
                <div className={"wr-state " + (w.status === "Paid" ? "paid" : "proc")}>{w.status}</div>
              </div>
            </div>
          ))}
        </div>
      </div>

      {sheet && (
        <div className="wallet-sheet-backdrop" onClick={() => sheet === "done" && setSheet(false)}>
          <div className="wallet-sheet" onClick={e => e.stopPropagation()}>
            {sheet === "form" ? (
              <>
                <div className="ws-grip" />
                <h3>Withdraw earnings</h3>
                <div className="ws-amount">{formatNGN(available)}</div>
                <div className="ws-field">
                  <span className="ws-flabel">To bank account</span>
                  <div className="ws-bank">
                    <span className="wr-icon out"><FFIcon name="bank" size={15} /></span>
                    <div>
                      <div style={{ fontWeight: 600, fontSize: 13 }}>GTBank ••4471</div>
                      <div style={{ fontSize: 11, color: "var(--muted)" }}>Tunde Adebayo</div>
                    </div>
                    <span style={{ marginLeft: "auto", fontSize: 11, color: "var(--accent-ink)", fontWeight: 600 }}>Change</span>
                  </div>
                </div>
                <div className="ws-note">Funds usually arrive within minutes. No withdrawal fee on the Folfem driver wallet.</div>
                <button className="btn btn-primary" style={{ width: "100%", justifyContent: "center", padding: 14, fontSize: 14 }} onClick={confirmWithdraw}>
                  Withdraw {formatNGN(available)}
                </button>
                <button className="btn btn-ghost" style={{ width: "100%", justifyContent: "center", marginTop: 8 }} onClick={() => setSheet(false)}>Cancel</button>
              </>
            ) : (
              <div style={{ textAlign: "center", padding: "8px 0 4px" }}>
                <div style={{ width: 56, height: 56, borderRadius: 28, background: "var(--accent-soft)", color: "var(--accent-ink)", display: "grid", placeItems: "center", margin: "0 auto 12px" }}>
                  <FFIcon name="check" size={26} stroke={2.5} />
                </div>
                <h3 style={{ margin: "0 0 4px" }}>Withdrawal started</h3>
                <div style={{ fontSize: 13, color: "var(--muted)", marginBottom: 16 }}>
                  {formatNGN(history[0]?.amount || 0)} is on its way to GTBank ••4471.
                </div>
                <button className="btn btn-primary" style={{ width: "100%", justifyContent: "center", padding: 14, fontSize: 14 }} onClick={() => setSheet(false)}>Done</button>
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
};

// === Mobile driver view (in iOS frame) ===

const DriverMobile = ({ jobs, driver, statusVariant, otpVariant, confirmVariant, advance, complete, sendMessage, pushToast }) => {
  const myJobs = jobs.filter(j => j.driverId === driver.id);
  const activeFirst = [...myJobs].sort((a, b) => STATUS_ORDER.indexOf(b.status) - STATUS_ORDER.indexOf(a.status));
  const [selectedId, setSelectedId] = useStateDriver(activeFirst.find(j => j.status !== "Delivered")?.id || activeFirst[0]?.id);
  const [view, setView] = useStateDriver("job"); // "job" | "list" | "wallet"

  useEffectDriver(() => {
    if (!myJobs.find(j => j.id === selectedId) && myJobs[0]) setSelectedId(myJobs[0].id);
  }, [myJobs.length]);

  const selected = myJobs.find(j => j.id === selectedId);
  if (!selected) return <div className="dm" style={{ padding: 24, color: "var(--muted)" }}>No jobs.</div>;

  // NOTE: JobBody() runs hooks, so it must be called unconditionally before any
  // view-based early return — otherwise React sees a changing hook count.
  const { mapBlock, routeBlock, cargoBlock, actionBlock } = JobBody({
    job: selected, statusVariant, otpVariant, confirmVariant,
    onAdvance: advance, onComplete: complete, sendMessage,
  });

  if (view === "wallet") {
    return <DriverWallet jobs={jobs} driver={driver} onBack={() => setView("job")} pushToast={pushToast} />;
  }

  if (view === "list") {
    return (
      <div className="dm">
        <div className="dm-head">
          <button className="menu" onClick={() => setView("job")} style={{ border: 0, cursor: "pointer" }}>
            <FFIcon name="chev" size={16} stroke={2.4} style={{ transform: "rotate(180deg)" }} />
          </button>
          <div className="who" style={{ marginLeft: 6 }}>
            <div className="nm">My jobs</div>
            <div style={{ fontSize: 11, color: "var(--muted)" }}>{myJobs.length} total</div>
          </div>
        </div>
        <div className="dm-body">
          {activeFirst.map(j => (
            <button key={j.id} className="dm-card" style={{ textAlign: "left", border: 0, padding: 12, width: "100%", cursor: "pointer", background: selectedId === j.id ? "var(--accent-soft)" : "var(--panel)" }} onClick={() => { setSelectedId(j.id); setView("job"); }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                <span className="mono" style={{ fontSize: 11, color: "var(--muted)" }}>{j.id}</span>
                <span className={"chip status-" + j.status} style={{ fontSize: 10, padding: "2px 6px" }}><span className="chip-dot" />{statusLabel(j.status)}</span>
              </div>
              <div style={{ fontWeight: 600, fontSize: 13, marginTop: 4 }}>{j.hub.name} → {j.delivery.name}</div>
              <div style={{ fontSize: 11, color: "var(--muted)", marginTop: 2 }}>{j.service} · {formatNGN(lastMilePayout(j))}</div>
            </button>
          ))}
        </div>
      </div>
    );
  }

  return (
    <div className="dm">
      <div className="dm-head">
        <span className="avatar av">{initials(driver.name)}</span>
        <div className="who">
          <div className="nm">{driver.name.split(" ")[0]}</div>
          <div className="st">On duty · {driver.city}</div>
        </div>
        <button className="menu" onClick={() => setView("wallet")} style={{ border: 0, cursor: "pointer" }} title="Wallet">
          <FFIcon name="wallet" size={16} />
        </button>
        <button className="menu" onClick={() => setView("list")} style={{ border: 0, cursor: "pointer" }} title="My jobs">
          <FFIcon name="list" size={16} />
        </button>
      </div>

      <div className="dm-body">
        <div className="dm-summary">
          <div className="label-row">
            <span className="mono" style={{ fontSize: 11, color: "var(--muted)" }}>{selected.id}</span>
            <span className={"chip status-" + selected.status}><span className="chip-dot" />{statusLabel(selected.status)}</span>
          </div>
          <h2>{selected.hub.name} → {selected.delivery.name}</h2>
          <div className="meta">{selected.service} · from {selected.client}</div>
        </div>

        {statusVariant === "map-first" && mapBlock}
        {routeBlock}
        {statusVariant !== "map-first" && statusVariant !== "list-compact" && mapBlock}
        {statusVariant !== "list-compact" && cargoBlock}

        <div className="dm-card">
          <h4>Progress</h4>
          <FlowSteps current={selected.status} history={selected.events} />
        </div>
      </div>

      <div className="dm-actions">
        {actionBlock}
      </div>
    </div>
  );
};

// === Driver view shell with mode switch ===

const DriverView = ({ jobs, drivers, statusVariant, otpVariant, confirmVariant, activeDriverId, setActiveDriverId, advance, complete, sendMessage, pushToast }) => {
  const [mode, setMode] = useStateDriver("mobile");
  const driver = drivers.find(d => d.id === activeDriverId) || drivers[0];

  return (
    <div style={{ flex: 1, display: "flex", flexDirection: "column", minHeight: 0 }}>
      <div className="driver-modeswitch">
        <div className="tabs">
          <button className={mode === "mobile" ? "active" : ""} onClick={() => setMode("mobile")}>
            <FFIcon name="phone" size={13} style={{ marginRight: 6, verticalAlign: "-2px" }} />Phone (driver)
          </button>
          <button className={mode === "desktop" ? "active" : ""} onClick={() => setMode("desktop")}>
            <FFIcon name="grid" size={13} style={{ marginRight: 6, verticalAlign: "-2px" }} />Desktop console
          </button>
        </div>
        <div className="meta" style={{ display: "flex", gap: 8, alignItems: "center" }}>
          <span>Acting as</span>
          <select className="select" style={{ padding: "4px 8px", fontSize: 12, width: "auto" }} value={driver.id} onChange={(e) => setActiveDriverId(e.target.value)}>
            {drivers.filter(d => d.region === "NG" && d.status !== "offline").map(d => (
              <option key={d.id} value={d.id}>{d.name} · {d.city}</option>
            ))}
          </select>
        </div>
      </div>

      {mode === "desktop" ? (
        <DriverDesktop jobs={jobs} driver={driver} statusVariant={statusVariant} otpVariant={otpVariant} confirmVariant={confirmVariant} advance={advance} complete={complete} sendMessage={sendMessage} />
      ) : (
        <div className="driver-shell" style={{ justifyContent: "center", alignItems: "center", padding: "20px 20px 40px", overflow: "auto" }}>
          <IOSDevice width={390} height={780}>
            <div style={{ height: "100%", paddingTop: 50, paddingBottom: 0, display: "flex", flexDirection: "column" }}>
              <DriverMobile jobs={jobs} driver={driver} statusVariant={statusVariant} otpVariant={otpVariant} confirmVariant={confirmVariant} advance={advance} complete={complete} sendMessage={sendMessage} pushToast={pushToast} />
            </div>
          </IOSDevice>
        </div>
      )}
    </div>
  );
};

window.DriverView = DriverView;
