// RUT241 eSIM Auto Provisioning — "+ Add RUT241" wizard (spec §4-13, 30).
// Simplified end-to-end flow per spec: Photo -> Confirm -> Asset ->
// Region -> Method -> Provision.
//
// Step 1  Take Photo / Upload Photo / Enter Manually
// Step 2  SOLO AI Vision review — confidence-banded fields, critical
//         fields always need explicit human confirmation (spec §8)
// Step 3  Assign to a SOLO asset (searchable)
// Step 4  Confirm deployment region — UK_EU or US_NA, never inferred
// Step 5  Select initial connection method — ESIM_BOOTSTRAP or WAN_ETHERNET
// Step 6  Review + submit -> POST /api/admin/rut241 (server runs the
//         full 13-step validation sequence, incl. duplicate + regional
//         hardware checks — this page surfaces whatever it returns)
//
// Reuses MiniField/ActionButton/ModalError/SectionLabel/EmptyNote/
// adminInputStyle/adminSelectStyle from admin-assets-page.jsx, AdminShell
// from admin-shell.jsx, and RUT241_REGION_LABELS from
// admin-rut241-dashboard-page.jsx — must load after all three.

const RUT241_CONFIDENCE_COLOR = {
  auto_accept: "rgba(20,140,60,0.95)",
  accept_display: "rgba(180,120,0,0.95)",
  manual_required: "rgba(190,40,40,0.95)",
};
const RUT241_CONFIDENCE_LABEL = {
  auto_accept: "Auto-accepted",
  accept_display: "Verify",
  manual_required: "Confirm required",
};

// spec §8's always-confirm-explicitly list, mirrored from
// lib/rut241.ts's CRITICAL_FIELDS for client-side display only (the
// server re-validates everything regardless).
const RUT241_CRITICAL_FIELDS = new Set(["model", "esim_capable", "serial_number", "lan_mac", "imei", "product_code", "admin_password"]);

const RUT241_FIELD_LABELS = {
  manufacturer: "Manufacturer",
  model: "Model",
  product_code: "Product / order code",
  hardware_revision: "Hardware revision",
  serial_number: "Serial number",
  imei: "IMEI",
  lan_mac: "LAN MAC",
  wifi_mac: "WiFi MAC",
  admin_username: "Admin username",
  admin_password: "Admin password",
  esim_capable: "eSIM capable",
};

const RUT241_STEP_LABELS = ["Photo", "Confirm device", "Assign asset", "Region", "Connection", "Review"];

function emptyRut241Fields() {
  return {
    manufacturer: "", model: "RUT241", product_code: "", hardware_revision: "",
    serial_number: "", imei: "", lan_mac: "", wifi_mac: "",
    admin_username: "", admin_password: "", esim_capable: "",
  };
}

function AdminRut241AddPage({ onNavigate }) {
  const [admin, setAdmin] = useState(null);
  const [loadStatus, setLoadStatus] = useState("loading");
  const [step, setStep] = useState(0); // 0..5
  const [mode, setMode] = useState(null); // "photo" | "manual"
  const [imageId, setImageId] = useState(null);
  const [imagePreviewUrl, setImagePreviewUrl] = useState(null);
  const [uploading, setUploading] = useState(false);
  const [extracting, setExtracting] = useState(false);
  const [fields, setFields] = useState(emptyRut241Fields());
  const [bands, setBands] = useState({}); // field_name -> band
  const [confirmed, setConfirmed] = useState({}); // field_name -> bool (explicit human confirmation)
  const [aiNotes, setAiNotes] = useState("");

  const [assetQuery, setAssetQuery] = useState("");
  const [assetResults, setAssetResults] = useState([]);
  const [assetSearching, setAssetSearching] = useState(false);
  const [selectedAsset, setSelectedAsset] = useState(null);

  const [region, setRegion] = useState("");
  const [connectionMethod, setConnectionMethod] = useState("");
  const [overrideRegionMismatch, setOverrideRegionMismatch] = useState(false);

  const [error, setError] = useState("");
  const [duplicateInfo, setDuplicateInfo] = useState(null);
  const [regionMismatchInfo, setRegionMismatchInfo] = useState(null);
  const [submitting, setSubmitting] = useState(false);

  const cameraInputRef = useRef(null);
  const uploadInputRef = useRef(null);

  useEffect(() => {
    Promise.all([
      fetch("/api/admin/me", { credentials: "same-origin" }).then((r) => (r.ok ? r.json() : Promise.reject())),
      fetch("/api/admin/rut241/me", { credentials: "same-origin" }).then((r) => (r.ok ? r.json() : Promise.reject())),
    ])
      .then(([me, rut241Me]) => {
        if (!rut241Me.permissions.includes("add_router")) {
          onNavigate("admin-rut241-dashboard");
          return;
        }
        setAdmin(me.admin);
        setLoadStatus("ready");
      })
      .catch(() => onNavigate("admin-login"));
  }, []); // eslint-disable-line react-hooks/exhaustive-deps -- mount-only

  const canOverrideRegion = admin && admin.role === "super_admin";

  // ---- Step 1: photo capture / upload / manual ----
  const handleFile = async (file) => {
    if (!file) return;
    setError("");
    setUploading(true);
    try {
      const formData = new FormData();
      formData.append("file", file);
      const res = await fetch("/api/admin/rut241/images", { method: "POST", credentials: "same-origin", body: formData });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) { setError(data.error || "Couldn't upload that photo."); setUploading(false); return; }
      setImageId(data.imageId);
      setImagePreviewUrl(`/api/admin/rut241/images/${data.imageId}/file`);
      setUploading(false);
      setMode("photo");
      runExtraction(data.imageId);
    } catch {
      setError("Couldn't reach the server. Check your connection and try again.");
      setUploading(false);
    }
  };

  const runExtraction = async (id) => {
    setExtracting(true);
    setError("");
    try {
      const res = await fetch(`/api/admin/rut241/images/${id}/extract`, { method: "POST", credentials: "same-origin" });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) { setError(data.error || "SOLO AI Vision couldn't read that label."); setExtracting(false); return; }
      const nextFields = emptyRut241Fields();
      const nextBands = {};
      const nextConfirmed = {};
      (data.fields || []).forEach((f) => {
        if (f.field in nextFields) nextFields[f.field] = f.value || (f.field === "esim_capable" ? "" : "");
        if (f.field === "esim_capable") nextFields.esim_capable = f.value === "YES" || f.value === "yes" || f.value === true ? "YES" : (f.value === "NO" || f.value === "no" ? "NO" : "");
        nextBands[f.field] = f.band;
        // Auto-accepted, non-critical fields start pre-confirmed; every
        // critical field (spec §8) always starts UNconfirmed regardless
        // of confidence, and low-confidence fields always start
        // unconfirmed too.
        nextConfirmed[f.field] = f.band === "auto_accept" && !RUT241_CRITICAL_FIELDS.has(f.field);
      });
      setFields(nextFields);
      setBands(nextBands);
      setConfirmed(nextConfirmed);
      setAiNotes(data.notes || "");
      setExtracting(false);
      setStep(1);
    } catch {
      setError("Couldn't reach the server. Check your connection and try again.");
      setExtracting(false);
    }
  };

  const startManual = () => {
    setMode("manual");
    setFields(emptyRut241Fields());
    setBands({});
    setConfirmed({});
    setImageId(null);
    setImagePreviewUrl(null);
    setStep(1);
  };

  const setField = (name, value) => {
    setFields((f) => ({ ...f, [name]: value }));
    // Editing a field after AI extraction counts as the human
    // reviewing/correcting it — treat as confirmed immediately.
    setConfirmed((c) => ({ ...c, [name]: true }));
  };

  const allCriticalConfirmed = Array.from(RUT241_CRITICAL_FIELDS).every((f) => confirmed[f] || mode === "manual");
  // In manual-entry mode there's no AI pass to confirm against — the
  // admin typing the value IS the confirmation, so this gate only
  // really bites in the AI-review path.
  const step1Valid = mode === "manual" ? true : allCriticalConfirmed;

  // ---- Step 3: asset search ----
  const searchAssets = (q) => {
    setAssetQuery(q);
    if (!q.trim()) { setAssetResults([]); return; }
    setAssetSearching(true);
    fetch(`/api/admin/rut241/assets/search?q=${encodeURIComponent(q.trim())}`, { credentials: "same-origin" })
      .then((r) => (r.ok ? r.json() : Promise.reject()))
      .then((data) => { setAssetResults(data.assets || []); setAssetSearching(false); })
      .catch(() => setAssetSearching(false));
  };

  // ---- Duplicate pre-check when leaving step 1 ----
  const checkDuplicateAndAdvance = async () => {
    setError("");
    try {
      const res = await fetch("/api/admin/rut241/check-duplicate", {
        method: "POST", credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ serial: fields.serial_number, imei: fields.imei, lanMac: fields.lan_mac }),
      });
      const data = await res.json().catch(() => ({}));
      if (data.duplicate) { setDuplicateInfo(data.duplicate); return; }
      setDuplicateInfo(null);
      setStep(2);
    } catch {
      setError("Couldn't reach the server. Check your connection and try again.");
    }
  };

  const submit = async () => {
    setSubmitting(true);
    setError("");
    setRegionMismatchInfo(null);
    try {
      const res = await fetch("/api/admin/rut241", {
        method: "POST", credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          asset_id: selectedAsset.id,
          region,
          initial_connection_method: connectionMethod,
          override_region_mismatch: overrideRegionMismatch,
          router: {
            model: fields.model, product_code: fields.product_code, hardware_revision: fields.hardware_revision,
            serial: fields.serial_number, imei: fields.imei, lan_mac: fields.lan_mac, wifi_mac: fields.wifi_mac,
            admin_username: fields.admin_username, admin_password: fields.admin_password,
            esim_capable: fields.esim_capable === "YES",
          },
          source: { image_id: imageId },
        }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) {
        if (data.code === "DUPLICATE_DEVICE") { setDuplicateInfo(data.existing); setStep(1); return; }
        if (data.code === "REGION_MISMATCH") { setRegionMismatchInfo(data.error); return; }
        setError(data.error || "Couldn't add this router.");
        return;
      }
      onNavigate("admin-rut241-router", { routerId: data.routerId });
    } catch {
      setError("Couldn't reach the server. Check your connection and try again.");
    } finally {
      setSubmitting(false);
    }
  };

  if (loadStatus === "loading") {
    return <section style={{ background: "#fff", minHeight: "calc(100vh - 88px)" }} />;
  }

  return (
    <AdminShell admin={admin} page="admin-rut241-dashboard" onNavigate={onNavigate}
      subtitle="RUT241 eSIM Auto Provisioning" title="Add RUT241.">
      <Rut241StepBar step={step} />
      {error && <ModalError>{error}</ModalError>}

      {step === 0 && (
        <Rut241PhotoStep
          uploading={uploading} extracting={extracting}
          cameraInputRef={cameraInputRef} uploadInputRef={uploadInputRef}
          onFile={handleFile} onManual={startManual}
        />
      )}

      {step === 1 && (
        <Rut241ConfirmStep
          mode={mode} imagePreviewUrl={imagePreviewUrl} fields={fields} bands={bands}
          confirmed={confirmed} aiNotes={aiNotes} onFieldChange={setField}
          onConfirmField={(name) => setConfirmed((c) => ({ ...c, [name]: true }))}
          duplicateInfo={duplicateInfo}
          onBack={() => { setStep(0); setMode(null); }}
          onNext={checkDuplicateAndAdvance}
          canNext={step1Valid}
        />
      )}

      {step === 2 && (
        <Rut241AssetStep
          query={assetQuery} results={assetResults} searching={assetSearching}
          selected={selectedAsset} onSearch={searchAssets} onSelect={setSelectedAsset}
          onBack={() => setStep(1)} onNext={() => setStep(3)}
        />
      )}

      {step === 3 && (
        <Rut241RegionStep
          region={region} onChange={setRegion}
          onBack={() => setStep(2)} onNext={() => setStep(4)}
        />
      )}

      {step === 4 && (
        <Rut241ConnectionStep
          method={connectionMethod} onChange={setConnectionMethod}
          onBack={() => setStep(3)} onNext={() => setStep(5)}
        />
      )}

      {step === 5 && (
        <Rut241ReviewStep
          fields={fields} asset={selectedAsset} region={region} connectionMethod={connectionMethod}
          regionMismatchInfo={regionMismatchInfo} canOverrideRegion={canOverrideRegion}
          overrideRegionMismatch={overrideRegionMismatch} onToggleOverride={setOverrideRegionMismatch}
          submitting={submitting}
          onBack={() => setStep(4)} onSubmit={submit}
        />
      )}
    </AdminShell>
  );
}

function Rut241StepBar({ step }) {
  return (
    <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 34 }}>
      {RUT241_STEP_LABELS.map((label, i) => (
        <div key={label} style={{
          display: "flex", alignItems: "center", gap: 8,
          fontFamily: "var(--font-body)", fontSize: 10.5, letterSpacing: "0.1em", textTransform: "uppercase",
          color: i === step ? "#000" : "rgba(0,0,0,0.35)", fontWeight: i === step ? 700 : 500,
        }}>
          <span style={{
            width: 20, height: 20, borderRadius: "50%", display: "flex", alignItems: "center", justifyContent: "center",
            background: i <= step ? "#000" : "rgba(0,0,0,0.08)", color: i <= step ? "#fff" : "rgba(0,0,0,0.4)",
            fontSize: 10,
          }}>{i + 1}</span>
          {label}
          {i < RUT241_STEP_LABELS.length - 1 && <span style={{ color: "rgba(0,0,0,0.2)", margin: "0 2px" }}>—</span>}
        </div>
      ))}
    </div>
  );
}

function Rut241PhotoStep({ uploading, extracting, cameraInputRef, uploadInputRef, onFile, onManual }) {
  const busy = uploading || extracting;
  return (
    <div>
      <SectionLabel>Step 1 — identify the router</SectionLabel>
      <div style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(0,0,0,0.6)", marginBottom: 24, maxWidth: 640, lineHeight: 1.6 }}>
        Photograph or upload the rear label of the RUT241 — SOLO AI Vision reads the model, serial, IMEI, MAC addresses, and admin credentials automatically. Or enter every field manually if no clear photo is available.
      </div>
      <div style={{ display: "flex", gap: 14, flexWrap: "wrap" }}>
        <input ref={cameraInputRef} type="file" accept="image/jpeg,image/jpg,image/png,image/heic,image/heif" capture="environment"
          style={{ display: "none" }} onChange={(e) => { const f = e.target.files && e.target.files[0]; e.target.value = ""; if (f) onFile(f); }} />
        <input ref={uploadInputRef} type="file" accept="image/jpeg,image/jpg,image/png,image/heic,image/heif"
          style={{ display: "none" }} onChange={(e) => { const f = e.target.files && e.target.files[0]; e.target.value = ""; if (f) onFile(f); }} />
        <ActionButton disabled={busy} onClick={() => cameraInputRef.current && cameraInputRef.current.click()} testId="rut241-take-photo">
          {uploading ? "Uploading…" : "Take Photo"}
        </ActionButton>
        <ActionButton disabled={busy} onClick={() => uploadInputRef.current && uploadInputRef.current.click()} testId="rut241-upload-photo">
          Upload Photo
        </ActionButton>
        <ActionButton disabled={busy} onClick={onManual} testId="rut241-enter-manually">
          Enter Manually
        </ActionButton>
      </div>
      {extracting && (
        <div style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(0,0,0,0.55)", marginTop: 24 }}>
          SOLO AI Vision is reading the label…
        </div>
      )}
    </div>
  );
}

function Rut241ConfirmStep({ mode, imagePreviewUrl, fields, bands, confirmed, aiNotes, onFieldChange, onConfirmField, duplicateInfo, onBack, onNext, canNext }) {
  const fieldOrder = ["model", "product_code", "hardware_revision", "manufacturer", "esim_capable", "serial_number", "imei", "lan_mac", "wifi_mac", "admin_username", "admin_password"];
  return (
    <div>
      <SectionLabel>Step 2 — confirm device details</SectionLabel>
      {duplicateInfo && (
        <ModalError>
          This router is already registered (serial {duplicateInfo.serial_number || duplicateInfo.asset_serial}, status {duplicateInfo.provisioning_status}). Choose a different device, or open the existing router instead.
        </ModalError>
      )}
      {aiNotes && (
        <div style={{ fontFamily: "var(--font-body)", fontSize: 12, color: "rgba(0,0,0,0.5)", marginBottom: 18, fontStyle: "italic" }}>
          SOLO AI Vision note: {aiNotes}
        </div>
      )}
      <div style={{ display: "flex", gap: 28, flexWrap: "wrap" }}>
        {mode === "photo" && imagePreviewUrl && (
          <div style={{ flex: "0 0 220px" }}>
            <img src={imagePreviewUrl} alt="RUT241 label" style={{ width: "100%", border: "1px solid rgba(0,0,0,0.15)" }} />
          </div>
        )}
        <div style={{ flex: "1 1 380px", display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))", gap: "4px 20px" }}>
          {fieldOrder.map((name) => (
            <Rut241FieldRow
              key={name} name={name} label={RUT241_FIELD_LABELS[name]}
              value={fields[name]} band={bands[name]} isConfirmed={!!confirmed[name]}
              isCritical={RUT241_CRITICAL_FIELDS.has(name)} mode={mode}
              onChange={(v) => onFieldChange(name, v)} onConfirm={() => onConfirmField(name)}
            />
          ))}
        </div>
      </div>
      {!canNext && mode === "photo" && (
        <div style={{ fontFamily: "var(--font-body)", fontSize: 12, color: "rgba(190,40,40,0.9)", marginTop: 18 }}>
          Every critical field (marked *) must be explicitly confirmed before continuing.
        </div>
      )}
      <Rut241WizardNav onBack={onBack} onNext={onNext} nextLabel="Continue" nextDisabled={!canNext} />
    </div>
  );
}

function Rut241FieldRow({ name, label, value, band, isConfirmed, isCritical, mode, onChange, onConfirm }) {
  const isEsim = name === "esim_capable";
  const isPassword = name === "admin_password";
  return (
    <MiniField label={`${label}${isCritical ? " *" : ""}`}>
      <div style={{ display: "flex", gap: 6, alignItems: "center" }}>
        {isEsim ? (
          <select value={value} onChange={(e) => onChange(e.target.value)} style={adminSelectStyle}>
            <option value="">Not confirmed</option>
            <option value="YES">YES</option>
            <option value="NO">NO</option>
          </select>
        ) : (
          <input
            value={value} onChange={(e) => onChange(e.target.value)}
            type={isPassword ? "text" : "text"}
            placeholder={mode === "manual" ? "Enter value…" : "Not detected"}
            style={adminInputStyle}
          />
        )}
      </div>
      {mode === "photo" && band && (
        <div style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 4 }}>
          <span style={{
            fontSize: 9.5, letterSpacing: "0.08em", textTransform: "uppercase", fontWeight: 600,
            color: RUT241_CONFIDENCE_COLOR[band],
          }}>{RUT241_CONFIDENCE_LABEL[band]}</span>
          {!isConfirmed && (
            <button type="button" onClick={onConfirm} style={{
              background: "none", border: "none", textDecoration: "underline", cursor: "pointer",
              fontSize: 9.5, letterSpacing: "0.06em", textTransform: "uppercase", color: "#000", padding: 0,
            }}>Confirm correct</button>
          )}
          {isConfirmed && <span style={{ fontSize: 9.5, color: "rgba(20,140,60,0.9)" }}>✓ Confirmed</span>}
        </div>
      )}
    </MiniField>
  );
}

function Rut241AssetStep({ query, results, searching, selected, onSearch, onSelect, onBack, onNext }) {
  return (
    <div>
      <SectionLabel>Step 3 — assign to a SOLO asset</SectionLabel>
      <div style={{ maxWidth: 480 }}>
        <MiniField label="Search assets by serial number, company, or asset id">
          <input value={query} onChange={(e) => onSearch(e.target.value)} placeholder="Start typing to search…" style={adminInputStyle} data-testid="rut241-asset-search" />
        </MiniField>
      </div>
      {searching && <div style={{ fontFamily: "var(--font-body)", fontSize: 12.5, color: "rgba(0,0,0,0.5)" }}>Searching…</div>}
      {!searching && query.trim() && results.length === 0 && (
        <EmptyNote>No matching assets found.</EmptyNote>
      )}
      <div style={{ display: "flex", flexDirection: "column", gap: 8, maxWidth: 560, marginTop: 8 }}>
        {results.map((a) => (
          <button
            key={a.id} type="button" onClick={() => onSelect(a)}
            style={{
              textAlign: "left", cursor: "pointer", padding: "12px 14px",
              background: selected && selected.id === a.id ? "#000" : "rgba(0,0,0,0.02)",
              color: selected && selected.id === a.id ? "#fff" : "#000",
              border: `1px solid ${selected && selected.id === a.id ? "#000" : "rgba(0,0,0,0.14)"}`,
              fontFamily: "var(--font-body)",
            }}
          >
            <div style={{ fontWeight: 600, fontSize: 13.5 }}>{a.product_name} — {a.serial_number}</div>
            <div style={{ fontSize: 11.5, opacity: 0.7, marginTop: 2 }}>
              Asset #{a.id} · {a.company_name || "Unassigned"} · {a.status}
            </div>
          </button>
        ))}
      </div>
      {selected && (
        <div style={{ fontFamily: "var(--font-body)", fontSize: 12.5, color: "rgba(20,140,60,0.9)", marginTop: 14 }}>
          ✓ Selected: {selected.product_name} — {selected.serial_number}
        </div>
      )}
      <Rut241WizardNav onBack={onBack} onNext={onNext} nextLabel="Continue" nextDisabled={!selected} />
    </div>
  );
}

function Rut241RegionStep({ region, onChange, onBack, onNext }) {
  return (
    <div>
      <SectionLabel>Step 4 — confirm deployment region</SectionLabel>
      <div style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(0,0,0,0.6)", marginBottom: 20, maxWidth: 560, lineHeight: 1.6 }}>
        This must be explicitly confirmed — SOLO never infers the region from the asset's owning company. It determines the router's eSIM pool and configuration profile.
      </div>
      <div style={{ display: "flex", gap: 14 }}>
        {Object.entries(RUT241_REGION_LABELS).map(([value, label]) => (
          <button
            key={value} type="button" onClick={() => onChange(value)}
            style={{
              padding: "20px 28px", cursor: "pointer", minWidth: 200, textAlign: "left",
              background: region === value ? "#000" : "rgba(0,0,0,0.02)", color: region === value ? "#fff" : "#000",
              border: `1px solid ${region === value ? "#000" : "rgba(0,0,0,0.14)"}`, fontFamily: "var(--font-body)",
            }}
            data-testid={`rut241-region-${value}`}
          >
            <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 15, textTransform: "uppercase" }}>{label}</div>
            <div style={{ fontSize: 11.5, opacity: 0.7, marginTop: 6 }}>{value}</div>
          </button>
        ))}
      </div>
      <Rut241WizardNav onBack={onBack} onNext={onNext} nextLabel="Continue" nextDisabled={!region} />
    </div>
  );
}

function Rut241ConnectionStep({ method, onChange, onBack, onNext }) {
  const options = [
    { value: "ESIM_BOOTSTRAP", label: "eSIM bootstrap", desc: "Router connects using the pre-installed bootstrap eSIM profile — no cable required." },
    { value: "WAN_ETHERNET", label: "WAN Ethernet", desc: "Router connects via a WAN cable for initial setup — must be physically removed and verified before the device can be marked Ready." },
  ];
  return (
    <div>
      <SectionLabel>Step 5 — initial connection method</SectionLabel>
      <div style={{ display: "flex", gap: 14, flexWrap: "wrap" }}>
        {options.map((o) => (
          <button
            key={o.value} type="button" onClick={() => onChange(o.value)}
            style={{
              padding: "18px 22px", cursor: "pointer", minWidth: 240, maxWidth: 300, textAlign: "left",
              background: method === o.value ? "#000" : "rgba(0,0,0,0.02)", color: method === o.value ? "#fff" : "#000",
              border: `1px solid ${method === o.value ? "#000" : "rgba(0,0,0,0.14)"}`, fontFamily: "var(--font-body)",
            }}
            data-testid={`rut241-method-${o.value}`}
          >
            <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 14, textTransform: "uppercase", marginBottom: 8 }}>{o.label}</div>
            <div style={{ fontSize: 12, opacity: 0.75, lineHeight: 1.5 }}>{o.desc}</div>
          </button>
        ))}
      </div>
      <Rut241WizardNav onBack={onBack} onNext={onNext} nextLabel="Continue" nextDisabled={!method} />
    </div>
  );
}

function Rut241ReviewStep({ fields, asset, region, connectionMethod, regionMismatchInfo, canOverrideRegion, overrideRegionMismatch, onToggleOverride, submitting, onBack, onSubmit }) {
  return (
    <div>
      <SectionLabel>Step 6 — review and provision</SectionLabel>
      {regionMismatchInfo && (
        <ModalError>
          {regionMismatchInfo}
          {canOverrideRegion && (
            <label style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 10, fontFamily: "var(--font-body)", fontSize: 12.5 }}>
              <input type="checkbox" checked={overrideRegionMismatch} onChange={(e) => onToggleOverride(e.target.checked)} />
              Override and provision anyway (super admin only — logged to the audit trail)
            </label>
          )}
        </ModalError>
      )}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))", gap: "10px 24px", maxWidth: 760, marginBottom: 24 }}>
        <Rut241ReviewRow label="Model" value={fields.model} />
        <Rut241ReviewRow label="Serial" value={fields.serial_number} />
        <Rut241ReviewRow label="IMEI" value={fields.imei} />
        <Rut241ReviewRow label="LAN MAC" value={fields.lan_mac} />
        <Rut241ReviewRow label="eSIM capable" value={fields.esim_capable} />
        <Rut241ReviewRow label="Product code" value={fields.product_code} />
        <Rut241ReviewRow label="Asset" value={asset ? `${asset.product_name} — ${asset.serial_number}` : "—"} />
        <Rut241ReviewRow label="Region" value={RUT241_REGION_LABELS[region] || region} />
        <Rut241ReviewRow label="Connection method" value={connectionMethod === "ESIM_BOOTSTRAP" ? "eSIM bootstrap" : "WAN Ethernet"} />
      </div>
      <Rut241WizardNav onBack={onBack} onNext={onSubmit} nextLabel={submitting ? "Provisioning…" : "Provision router"} nextDisabled={submitting} />
    </div>
  );
}

function Rut241ReviewRow({ label, value }) {
  return (
    <div>
      <div style={{ fontFamily: "var(--font-body)", fontSize: 9.5, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.45)", marginBottom: 3 }}>{label}</div>
      <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "#000" }}>{value || "—"}</div>
    </div>
  );
}

function Rut241WizardNav({ onBack, onNext, nextLabel, nextDisabled }) {
  return (
    <div style={{ display: "flex", gap: 12, marginTop: 32, borderTop: "1px solid rgba(0,0,0,0.1)", paddingTop: 24 }}>
      {onBack && <ActionButton onClick={onBack} testId="rut241-wizard-back">Back</ActionButton>}
      <ActionButton onClick={onNext} disabled={nextDisabled} testId="rut241-wizard-next">{nextLabel}</ActionButton>
    </div>
  );
}

Object.assign(window, { AdminRut241AddPage });
