/* ========================================================================
   estate.jsx — International SIMs and Travel eSIMs (Story 1, structure)
   Group cards on SIM Management, Estate by Country on Overview, and
   group-aware SIM detail variants. Loads after sim-manage.jsx and
   data-pool.jsx so it can wrap SimShowPage and UserSimCard.
   ======================================================================== */
const { useState: uE, useMemo: mE } = React;
const EST = window.MP_ESTATE;
const EDATA = window.MILO_DATA;
const BaseSimShowPage = window.SimShowPage;
const BaseUserSimCard = window.UserSimCard;

const estUser = (sim) => EDATA.USERS.find((u) => u.sim_ids.includes(sim.id)) || null;
const coverageOf = (sim) => EST.COVERAGE[sim.coverage] || { label: "—", countries: 1 };

/* ---------- Primitives ---------- */
function FreshnessStamp({ chip }) {
  const text = "Usage updated monthly · Last updated " + EST.loadLabelFull;
  if (chip) return <span className="mp-fresh-chip"><Icon name="info" size={12} />{text}</span>;
  return <span className="mp-fresh"><Icon name="info" size={13} />{text}</span>;
}

function AllowanceFlag({ sim }) {
  const st = EST.allowanceState(sim);
  return (
    <span className={"mp-allow-flag mp-allow-flag--" + (st.over ? "over" : "within")}>
      <Icon name={st.over ? "triangle-alert" : "circle-check"} size={14} />
      {st.label}
    </span>);
}

function CountryLabel({ code }) {
  const c = EST.COUNTRIES[code];
  if (!c) return <span>—</span>;
  return <span className="mp-country-cell"><span className="mp-country-flag">{c.flag}</span>{c.name}</span>;
}

function CountryTile({ row, active, onClick }) {
  return (
    <button type="button" className={"mp-country-tile" + (active ? " is-active" : "")} onClick={onClick} aria-pressed={active}>
      <span className="mp-country-flag">{row.flag}</span>
      <span className="mp-country-body">
        <span className="mp-country-name">{row.name}</span>
        <span className="mp-country-net">{row.network}</span>
        <span className="mp-country-figs">
          <span><strong>{row.count}</strong> SIM{row.count === 1 ? "" : "s"}</span>
          <span><strong>{EST.estGb(row.used)} GB</strong></span>
        </span>
      </span>
    </button>);
}

function MonthlyUsageCell({ sim }) {
  if (EST.awaitingFirstMonth(sim)) return <span className="mp-mu-none">No usage yet</span>;
  const over = sim.used > sim.allowance_gb;
  return (
    <span className={"mp-mu-line" + (over ? " is-over" : "")}>
      <b>{EST.estGb(sim.used)} GB</b> of {sim.allowance_gb} GB ({EST.monthLabel})
    </span>);
}

/* Travel usage is live, so it reads like a UK SIM: a bar and current figures.
   Figures come from the plan the eSIM is running on, not the eSIM itself. */
function travelRead(sim) {
  return window.MP_TRAVEL ? window.MP_TRAVEL.travelSummary(sim) :
    { plan: null, allowance_gb: sim.allowance_gb, used: sim.used, awaiting: false, expires: sim.expires, renews_on: sim.renews_on, count: 1 };
}
function TravelUsageCell({ sim }) {
  const r = travelRead(sim);
  if (r.awaiting) return <div className="mp-mu"><span>No usage yet</span><span>Awaiting first use</span></div>;
  const pct = Math.min(100, Math.round(r.used / r.allowance_gb * 100));
  const over = r.used > r.allowance_gb;
  return (
    <div className={"mp-mu" + (over ? " is-over" : "")}>
      <b>{EST.estGb(r.used)} GB</b>
      <span className="mp-sim-data-bar"><span style={{ width: pct + "%" }} /></span>
      <span>{r.expires ?
        "of " + r.allowance_gb + " GB · Plan ends " + EST.fmtDate(r.expires) :
        "of " + r.allowance_gb + " GB this month"}</span>
    </div>);
}

/* 10 — validity reads as its own fact, and says when it is close. */
function ValidityCell({ summary }) {
  if (summary.awaiting) return <span className="mp-validity mp-validity--awaiting"><Icon name="clock" size={12} />Awaiting first use</span>;
  const when = summary.expires || summary.renews_on;
  if (!when) return <span className="mp-validity">Not set</span>;
  const days = (when - new Date()) / 86400000;
  const soon = !!summary.expires && days <= 30;
  return (
    <span className={"mp-validity" + (soon ? " mp-validity--soon" : "")}>
      <Icon name={summary.expires ? "calendar" : "rotate-ccw"} size={12} />
      {(summary.expires ? "Expires " : "Renews ") + EST.fmtDate(when)}
    </span>);
}

/* ---------- Sorting / paging shared by both estate tables ---------- */
function useEstateTable(rows, defaultField, keyFor, perPage) {
  const [sortField, setSortField] = uE(defaultField);
  const [sortDir, setSortDir] = uE("asc");
  const [page, setPage] = uE(1);
  const onSort = (f) => { if (sortField === f) setSortDir(sortDir === "asc" ? "desc" : "asc"); else { setSortField(f); setSortDir("asc"); } };
  const sorted = mE(() => {
    const r = rows.slice(); const dir = sortDir === "asc" ? 1 : -1;
    r.sort((a, b) => { const A = keyFor(a, sortField), B = keyFor(b, sortField); return A > B ? dir : A < B ? -dir : 0; });
    return r;
  }, [rows, sortField, sortDir]);
  const totalPages = Math.ceil(sorted.length / perPage) || 1;
  const safePage = Math.min(page, totalPages);
  return { sortField, sortDir, onSort, pageRows: sorted.slice((safePage - 1) * perPage, safePage * perPage), page: safePage, totalPages, setPage };
}

function EstateEmpty() {
  return (
    <div className="mp-empty" style={{ padding: "26px 0" }}>
      <div className="mp-empty-title">No SIMs match</div>
      <div className="mp-empty-msg">Try a different search or clear the filters.</div>
    </div>);
}

const EST_STATUS_OPTIONS = [
  { value: "", label: "All statuses" },
  { value: "Active", label: "Active" },
  { value: "For Activation", label: "For Activation" },
  { value: "Suspended", label: "Suspended" },
  { value: "Terminated", label: "Terminated" }];

/* ---------- International SIMs table ---------- */
function InternationalTable({ rows, bulk }) {
  const t = useEstateTable(rows, "serial", (s, f) =>
    f === "serial" ? s.serial : f === "sim_type" ? s.sim_type : f === "status" ? s.status :
    f === "assigned_user" ? (estUser(s) || {}).full_name || "" :
    f === "msisdn" ? s.msisdn : f === "country" ? EST.COUNTRIES[s.country].name :
    f === "network" ? s.network : f === "used" ? s.used : s.serial, 10);
  if (!rows.length) return <EstateEmpty />;
  return (
    <>
      <TableScroll>
        <table className="mp-table">
          <thead>
            <tr>
              {bulk && bulk.on ? <window.BulkCheckHead bulk={bulk} pageRows={t.pageRows} /> : null}
              <th><SortHeader field="serial" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>SIM Serial</SortHeader></th>
              <th><SortHeader field="sim_type" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>SIM Type</SortHeader></th>
              <th><SortHeader field="status" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Status</SortHeader></th>
              <th><SortHeader field="assigned_user" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Assigned User</SortHeader></th>
              <th><SortHeader field="msisdn" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Local Number</SortHeader></th>
              <th><SortHeader field="country" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Country</SortHeader></th>
              <th><SortHeader field="network" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Network</SortHeader></th>
              <th><SortHeader field="allowance" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Data Plan</SortHeader></th>
              <th><SortHeader field="used" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Usage</SortHeader></th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {t.pageRows.map((sim) => {
              const user = estUser(sim);
              return (
                <tr key={sim.id}>
                  {bulk && bulk.on ? <window.BulkCheckCell bulk={bulk} sim={sim} /> : null}
                  <td className="mp-mono">{sim.serial}</td>
                  <td><SimTypeBadge type={sim.sim_type} /></td>
                  <td>
                    <span className="mp-status-cell">
                      <StatusBadge status={window.MP_REQ.estStatus(sim)} sim={sim} />
                      {window.RequestRowChip ? <window.RequestRowChip sim={sim} /> : null}
                    </span>
                  </td>
                  <td>{user ? <a href={"#/users/" + user.id} className="mp-assigned"><Avatar initials={user.initials} size={26} tone="mist" /><span>{user.full_name}</span></a> : <span style={{ color: "var(--fg-3)" }}>—</span>}</td>
                  <td className="mp-mono">{sim.msisdn}</td>
                  <td><CountryLabel code={sim.country} /></td>
                  <td>{sim.network}</td>
                  <td>{sim.allowance_gb} GB</td>
                  <td><MonthlyUsageCell sim={sim} /></td>
                  <td><ActionsMenu items={[{ label: "View Details", href: "#/sims/" + sim.id }]} /></td>
                </tr>);
            })}
          </tbody>
        </table>
      </TableScroll>
      {t.totalPages > 1 ? <div style={{ padding: "12px 16px" }}><Pagination page={t.page} totalPages={t.totalPages} onChange={t.setPage} /></div> : null}
    </>);
}

/* ---------- International SIMs group card ---------- */
function InternationalSimsPanel({ initialOpen, initialCountry }) {
  const rows = EST.internationalSims();
  const [open, setOpen] = uE(!!initialOpen);
  const [query, setQuery] = uE("");
  const [status, setStatus] = uE("");
  const [assignment, setAssignment] = uE("");
  const [country, setCountry] = uE(initialCountry || "");
  const [asking, setAsking] = uE(false);
  const ctx = window.useRoles ? window.useRoles() : null;
  window.MP_REQ.useRequests();
  const summary = EST.countrySummary();

  const filtered = mE(() => {
    let r = rows;
    if (query.trim()) {
      const q = query.trim().toLowerCase();
      r = r.filter((s) => s.serial.toLowerCase().includes(q) || (s.msisdn || "").toLowerCase().includes(q) ||
        (estUser(s) || {}).full_name?.toLowerCase().includes(q));
    }
    if (status) r = r.filter((s) => window.MP_REQ.estStatus(s) === status);
    if (country) r = r.filter((s) => s.country === country);
    if (assignment) r = r.filter((s) => assignment === "assigned" ? !!estUser(s) : !estUser(s));
    return r;
  }, [rows, query, status, country, assignment]);

  const active = rows.filter((s) => window.MP_REQ.estStatus(s) !== "Terminated").length;
  const dirty = query || status || country || assignment;
  const bulk = window.useBulkScope("international", filtered, "international");
  if (!rows.length) return null;

  return (
    <Card style={{ overflow: "hidden" }}>
      <div className="mp-sim-bar">
        <div>
          <div className="mp-pool-hero-eyebrow">International SIMs</div>
          <h2 className="mp-sim-hero-number">{active} SIMs <span className="mp-pool-hero-tot">· {summary.length} countr{summary.length === 1 ? "y" : "ies"}</span></h2>
          <div className="mp-sim-hero-meta">
            <span>Usage updated monthly</span>
            <span className="mp-dot-sep">•</span>
            <span>Last updated {EST.loadLabelFull}</span>
          </div>
        </div>
        {MP_ALLOW("sim.order") ?
        <div className="mp-sim-hero-actions">
          <Button variant="secondary" icon="globe" onClick={() => setAsking(true)}>Request International SIMs</Button>
        </div> : null}
      </div>

      <button type="button" className={"mp-sim-disclosure" + (open ? " is-open" : "")} onClick={() => setOpen((o) => !o)} aria-expanded={open}>
        <Icon name="chevron-down" size={16} />
        <span>{open ? "Hide" : "Show"} international SIMs</span>
      </button>

      {open ?
      <div className="mp-sim-details">
        <div className="mp-country-strip">
          {summary.map((r) =>
            <CountryTile key={r.code} row={r} active={country === r.code} onClick={() => setCountry(country === r.code ? "" : r.code)} />)}
        </div>
        <div className="mp-group-sims">
          <div className="mp-mem-filters">
            <SearchInput value={query} onChange={setQuery} placeholder="Search international SIMs…" />
            <Select value={status} onChange={setStatus} options={EST_STATUS_OPTIONS} />
            <Select value={assignment} onChange={setAssignment} placeholder="All assignments"
              options={[{ value: "assigned", label: "Assigned SIMs" }, { value: "unassigned", label: "Unassigned SIMs" }]} />
            <Select value={country} onChange={setCountry} placeholder="All countries"
              options={summary.map((r) => ({ value: r.code, label: r.name }))} />
            <window.BulkToggleButton bulk={bulk} />
            {dirty ?
            <div className="mp-clear">
              <Button variant="secondary" size="sm" icon="x" onClick={() => { setQuery(""); setStatus(""); setAssignment(""); setCountry(""); }}>Clear Filters</Button>
            </div> : null}
          </div>
          <InternationalTable rows={filtered} bulk={bulk} />
          <window.BulkBar bulk={bulk} tweaks={window.MP_TWEAKS} />
        </div>
      </div> : null}
      {asking ?
      <window.RequestNewSimsModal onClose={() => setAsking(false)}
        onSent={() => {
          setAsking(false);
          if (ctx) ctx.toast({ kind: "ok", title: "Request sent", body: "The team will be in touch to arrange your SIMs." });
        }} /> : null}
    </Card>);
}

/* ---------- Travel eSIMs table ---------- */
function TravelTable({ rows, bulk }) {
  const t = useEstateTable(rows, "user", (s, f) => {
    const u = estUser(s);
    return f === "user" ? (u ? u.full_name : "") : f === "coverage" ? coverageOf(s).label :
      f === "allowance" ? s.allowance_gb : f === "plan_type" ? s.plan_type :
      f === "used" ? s.used : f === "status" ? s.status :
      f === "expires" ? (function() { var r = travelRead(s); var d = r.expires || r.renews_on; return d ? d.getTime() : 0; })() :
      (u ? u.full_name : "");
  }, 10);
  if (!rows.length) return <EstateEmpty />;
  return (
    <>
      <TableScroll>
        <table className="mp-table">
          <thead>
            <tr>
              {bulk && bulk.on ? <window.BulkCheckHead bulk={bulk} pageRows={t.pageRows} /> : null}
              <th><SortHeader field="user" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>User</SortHeader></th>
              <th><SortHeader field="coverage" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Coverage</SortHeader></th>
              <th><SortHeader field="allowance" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Allowance</SortHeader></th>
              <th><SortHeader field="plan_type" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Plan Type</SortHeader></th>
              <th><SortHeader field="used" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Usage</SortHeader></th>
              <th><SortHeader field="status" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Status</SortHeader></th>
              <th><SortHeader field="expires" sortField={t.sortField} sortDir={t.sortDir} onSort={t.onSort}>Expires / Renews</SortHeader></th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {t.pageRows.map((sim) => {
              const user = estUser(sim);
              const r = travelRead(sim);
              const cov = coverageOf(sim);
              return (
                <tr key={sim.id}>
                  {bulk && bulk.on ? <window.BulkCheckCell bulk={bulk} sim={sim} /> : null}
                  <td>{user ? <a href={"#/users/" + user.id} className="mp-assigned"><Avatar initials={user.initials} size={26} tone="mist" /><span>{user.full_name}</span></a> : <span style={{ color: "var(--fg-3)" }}>—</span>}</td>
                  <td>{cov.label}{r.count > 1 ? <span className="mp-plan-count"> +{r.count - 1} more</span> : null}</td>
                  <td>{r.allowance_gb} GB</td>
                  <td>{r.type === "recurring" ? "Recurring" : "One-Off"}</td>
                  <td><TravelUsageCell sim={sim} /></td>
                  <td><StatusBadge status={sim.status} sim={sim} /></td>
                  <td><ValidityCell summary={r} /></td>
                  <td><ActionsMenu items={[{ label: "View Details", href: "#/sims/" + sim.id }]} /></td>
                </tr>);
            })}
          </tbody>
        </table>
      </TableScroll>
      {t.totalPages > 1 ? <div style={{ padding: "12px 16px" }}><Pagination page={t.page} totalPages={t.totalPages} onChange={t.setPage} /></div> : null}
    </>);
}

/* ---------- Travel eSIMs group card ---------- */
function TravelEsimsPanel({ initialOpen }) {
  const rows = EST.travelSims();
  window.MP_TRAVEL.useTravel();
  const [open, setOpen] = uE(!!initialOpen);
  const [query, setQuery] = uE("");
  const [coverage, setCoverage] = uE("");
  const [status, setStatus] = uE("");

  const filtered = mE(() => {
    let r = rows;
    if (query.trim()) {
      const q = query.trim().toLowerCase();
      r = r.filter((s) => s.serial.toLowerCase().includes(q) || coverageOf(s).label.toLowerCase().includes(q) ||
        (estUser(s) || {}).full_name?.toLowerCase().includes(q));
    }
    if (coverage) r = r.filter((s) => s.coverage === coverage);
    if (status) r = r.filter((s) => s.status === status);
    return r;
  }, [rows, query, coverage, status]);

  const activeCount = rows.filter((s) => s.status === "Active").length;
  const soon = rows.filter((s) => {
    const r = travelRead(s);
    return r.expires && (r.expires - new Date()) / 86400000 <= 30;
  }).length;
  const dirty = query || coverage || status;
  const coverageOpts = Object.keys(EST.COVERAGE)
    .filter((k) => rows.some((s) => s.coverage === k))
    .map((k) => ({ value: k, label: EST.COVERAGE[k].label }));
  const bulk = window.useBulkScope("travel", filtered, "travel");
  if (!rows.length) return null;

  return (
    <Card style={{ overflow: "hidden" }}>
      <div className="mp-sim-bar">
        <div>
          <div className="mp-pool-hero-eyebrow">Travel eSIMs</div>
          <h2 className="mp-sim-hero-number">{activeCount} active{soon > 0 ? <span className="mp-pool-hero-tot"> · {soon} expiring within 30 days</span> : null}</h2>
        </div>
        {MP_ALLOW("sim.order") ?
        <div className="mp-sim-hero-actions">
          <Button variant="secondary" icon="plus" href="#/sims/travel/new">Add Travel eSIM Plan</Button>
        </div> : null}
      </div>

      <button type="button" className={"mp-sim-disclosure" + (open ? " is-open" : "")} onClick={() => setOpen((o) => !o)} aria-expanded={open}>
        <Icon name="chevron-down" size={16} />
        <span>{open ? "Hide" : "Show"} travel eSIMs</span>
      </button>

      {open ?
      <div className="mp-sim-details">
        <div className="mp-group-sims">
          <div className="mp-mem-filters">
            <SearchInput value={query} onChange={setQuery} placeholder="Search travel eSIMs…" />
            <Select value={coverage} onChange={setCoverage} placeholder="All coverage" options={coverageOpts} />
            <Select value={status} onChange={setStatus} options={EST_STATUS_OPTIONS} />
            <window.BulkToggleButton bulk={bulk} />
            {dirty ?
            <div className="mp-clear">
              <Button variant="secondary" size="sm" icon="x" onClick={() => { setQuery(""); setCoverage(""); setStatus(""); }}>Clear Filters</Button>
            </div> : null}
          </div>
          <TravelTable rows={filtered} bulk={bulk} />
          <window.BulkBar bulk={bulk} tweaks={window.MP_TWEAKS} />
        </div>
      </div> : null}
    </Card>);
}

/* ---------- Group-aware SIM detail ---------- */
/* Usage sections render inside the shared disclosure, not as their own cards. */
function EstateUsageBlock({ sim }) {
  if (EST.awaitingFirstMonth(sim)) return (
    <div>
      <h4>Data Usage</h4>
      <Empty icon="info" title="No usage yet"
        message={"First month's usage will appear after " + EST.monthEndLabel + "."} />
    </div>);
  const over = sim.used > sim.allowance_gb;
  return (
    <div>
      <h4>Data Usage</h4>
      <div className="mp-usage-months">
        <div className="mp-usage-month">
          <div className="mp-usage-month-label">{EST.monthFull}</div>
          <div className="mp-usage-month-val">{EST.estGb(sim.used)} GB</div>
          <div className="mp-usage-month-sub">of {sim.allowance_gb} GB allowance</div>
        </div>
      </div>
      {over ? <AllowanceFlag sim={sim} /> : null}
      <div style={{ marginTop: 12 }}><FreshnessStamp chip /></div>
    </div>);
}

function InternationalSimDetail({ sim }) {
  const c = EST.COUNTRIES[sim.country];
  const user = estUser(sim);
  const [drawer, setDrawer] = uE(false);
  const [open, setOpen] = uE(false);
  const [editing, setEditing] = uE(false);
  const savedImei = (window.loadSimState ? window.loadSimState(sim) : {}).imei;
  const [imei, setImei] = uE(savedImei || (window.simImei ? window.simImei(sim) : "—"));
  window.MP_REQ.useRequests();
  React.useEffect(() => { if (window.lucide) { try { window.lucide.createIcons(); } catch (e) {} } });
  return (
    <>
      <PageHead title="SIM Management" />
      <BackLink href="#/sims?group=international">Back to SIMs</BackLink>

      <Card>
        <div className="mp-sim-bar">
          <div>
            <div className="mp-pool-hero-eyebrow">International SIM Details</div>
            <h2 className="mp-sim-hero-number">{sim.msisdn}</h2>
            <div className="mp-estate-facts">
              <CountryLabel code={sim.country} />
              <span className="mp-dot-sep">•</span>
              <span>{sim.network}</span>
              <span className="mp-dot-sep">•</span>
              <span className="mp-group-chip mp-group-chip--intl"><Icon name="globe" size={11} />International</span>
            </div>
            <div className="mp-sim-hero-meta" style={{ marginTop: 10 }}>
              {user ?
                <>
                  <Avatar initials={user.initials} size={26} tone="mist" />
                  <span>Assigned to <a href={"#/users/" + user.id} style={{ color: "var(--mp-pine)", fontWeight: 700, textDecoration: "underline" }}>{user.full_name}</a></span>
                </> :
                <span style={{ color: "var(--fg-3)" }}>Unassigned</span>}
              <span className="mp-dot-sep">•</span>
              <SimTypeBadge type={sim.sim_type} />
              <StatusBadge status={window.MP_REQ.estStatus(sim)} sim={sim} />
            </div>
          </div>
          {MP_ALLOW("sim.manage") ?
          <div className="mp-sim-hero-actions">
            <Button variant="primary" icon="send" onClick={() => setDrawer(true)}>Make a Request</Button>
          </div> : null}
        </div>
        <div className="mp-sim-banner-wrap"><window.RequestBanner sim={sim} /></div>

        <button type="button" className={"mp-sim-disclosure" + (open ? " is-open" : "")}
          onClick={() => setOpen((o) => !o)} aria-expanded={open}>
          <Icon name="chevron-down" size={16} />
          <span>{open ? "Hide" : "Show"} usage and full SIM details</span>
        </button>

        {open ?
        <div className="mp-sim-details">
          <div className="mp-estate-detail-grid">
            <EstateUsageBlock sim={sim} />
            <div>
              <h4>SIM Card Information</h4>
              <div className="mp-kv-grid">
                <KvCell label="Local Number" value={sim.msisdn} />
                <KvCell label="SIM Serial" value={sim.serial} />
                <KvCell label="IMEI" value={imei}
                  action={MP_ALLOW("sim.manage") ?
                    <button type="button" className="mp-kv-edit" onClick={() => setEditing(true)} aria-label="Edit IMEI"><Icon name="pencil" size={13} /></button> : null} />
                <KvCell label="SIM Type" value={sim.sim_type} />
                <KvCell label="Country" value={c.name} />
                <KvCell label="Network" value={sim.network} />
                <KvCell label="Activation Date" value={fmtActivation(sim.activation_date)} />
              </div>
            </div>
          </div>
          <div className="mp-estate-plan" style={{ marginTop: 22 }}>
            <h4 style={{ margin: "0 0 12px", fontSize: 15, fontWeight: 700, color: "var(--mp-deep-forest)" }}>Plan Inclusions</h4>
            <div className="mp-kv-grid">
              <KvCell label="Calls" value={sim.calls} />
              <KvCell label="Texts" value={sim.texts} />
              <KvCell label="Data" value={sim.allowance_gb + " GB"} />
              {sim.eu_roaming ? <KvCell label="EU Roaming" value="Included" /> : null}
            </div>
          </div>
        </div> : null}
      </Card>

      {window.EsimInstallCard ? <window.EsimInstallCard sim={sim} /> : null}

      {editing && window.EditImeiDialog ?
      <window.EditImeiDialog current={imei} onCancel={() => setEditing(false)}
        onConfirm={(v) => { setImei(v); if (window.persistSimState) window.persistSimState(sim.id, { imei: v }); setEditing(false); }} /> : null}

      {drawer ? <window.RequestChangeDrawer sim={sim} onClose={() => setDrawer(false)} /> : null}
    </>);
}

/* ---------- Individual SIM on an alternative network ----------
   International detail skeleton without the country facts, with the network.
   Usage is live, so it uses the UK usage ring rather than the monthly block. */
function AltNetUsageBlock({ sim }) {
  const plan = EDATA.PLANS[sim.plan] || {};
  return (
    <div>
      <h4>Data Usage</h4>
      <div className="mp-usage-ring-wrap"><UsageRing used={sim.used} limit={plan.limit_gb} /></div>
      <div className="mp-usage-stats">
        <KV label="Plan allowance" value={plan.data} />
        <KV label="Used this period" value={sim.used.toFixed(1) + " GB"} />
        {plan.limit_gb ? <KV label="Remaining" value={Math.max(0, plan.limit_gb - sim.used).toFixed(1) + " GB"} /> : null}
      </div>
    </div>);
}

function AltNetSimDetail({ sim }) {
  const user = estUser(sim);
  const plan = EDATA.PLANS[sim.plan] || {};
  const [drawer, setDrawer] = uE(false);
  const [open, setOpen] = uE(false);
  const [editing, setEditing] = uE(false);
  const savedImei = (window.loadSimState ? window.loadSimState(sim) : {}).imei;
  const [imei, setImei] = uE(savedImei || (window.simImei ? window.simImei(sim) : "—"));
  window.MP_REQ.useRequests();
  React.useEffect(() => { if (window.lucide) { try { window.lucide.createIcons(); } catch (e) {} } });
  return (
    <>
      <PageHead title="SIM Management" />
      <BackLink href="#/sims?group=altnet">Back to SIMs</BackLink>

      <Card>
        <div className="mp-sim-bar">
          <div>
            <div className="mp-pool-hero-eyebrow">Individual SIM Details</div>
            <h2 className="mp-sim-hero-number">{sim.msisdn}</h2>
            <div className="mp-estate-facts">
              <span>{sim.network}</span>
              <span className="mp-dot-sep">•</span>
              <span className="mp-group-chip mp-group-chip--ind"><Icon name="card-sim" size={11} />Other Network</span>
            </div>
            <div className="mp-sim-hero-meta" style={{ marginTop: 10 }}>
              {user ?
                <>
                  <Avatar initials={user.initials} size={26} tone="mist" />
                  <span>Assigned to <a href={"#/users/" + user.id} style={{ color: "var(--mp-pine)", fontWeight: 700, textDecoration: "underline" }}>{user.full_name}</a></span>
                </> :
                <span style={{ color: "var(--fg-3)" }}>Unassigned</span>}
              <span className="mp-dot-sep">•</span>
              <SimTypeBadge type={sim.sim_type} />
              <StatusBadge status={window.MP_REQ.estStatus(sim)} sim={sim} />
            </div>
          </div>
          {MP_ALLOW("sim.manage") ?
          <div className="mp-sim-hero-actions">
            <Button variant="primary" icon="send" onClick={() => setDrawer(true)}>Make a Request</Button>
          </div> : null}
        </div>
        <div className="mp-sim-banner-wrap"><window.RequestBanner sim={sim} /></div>

        <button type="button" className={"mp-sim-disclosure" + (open ? " is-open" : "")}
          onClick={() => setOpen((o) => !o)} aria-expanded={open}>
          <Icon name="chevron-down" size={16} />
          <span>{open ? "Hide" : "Show"} usage and full SIM details</span>
        </button>

        {open ?
        <div className="mp-sim-details">
          <div className="mp-estate-detail-grid">
            <AltNetUsageBlock sim={sim} />
            <div>
              <h4>SIM Card Information</h4>
              <div className="mp-kv-grid">
                <KvCell label="Assigned Number" value={sim.msisdn} />
                <KvCell label="SIM Serial" value={sim.serial} />
                <KvCell label="IMEI" value={imei}
                  action={MP_ALLOW("sim.manage") ?
                    <button type="button" className="mp-kv-edit" onClick={() => setEditing(true)} aria-label="Edit IMEI"><Icon name="pencil" size={13} /></button> : null} />
                <KvCell label="SIM Type" value={sim.sim_type} />
                <KvCell label="Network" value={sim.network} />
                <KvCell label="Data Plan" value={plan.data} />
                <KvCell label="Activation Date" value={fmtActivation(sim.activation_date)} />
              </div>
            </div>
          </div>
        </div> : null}
      </Card>

      {window.EsimInstallCard ? <window.EsimInstallCard sim={sim} /> : null}

      {editing && window.EditImeiDialog ?
      <window.EditImeiDialog current={imei} onCancel={() => setEditing(false)}
        onConfirm={(v) => { setImei(v); if (window.persistSimState) window.persistSimState(sim.id, { imei: v }); setEditing(false); }} /> : null}

      {drawer ? <window.RequestChangeDrawer sim={sim} onClose={() => setDrawer(false)} /> : null}
    </>);
}

/* User page card for an alternative network SIM. */
function AltNetUserSimCard({ sim }) {
  const [open, setOpen] = uE(false);
  window.MP_REQ.useRequests();
  const plan = EDATA.PLANS[sim.plan] || {};
  return (
    <Card style={{ overflow: "hidden" }}>
      <div className="mp-sim-bar">
        <div>
          <div className="mp-estate-card-kind">Individual SIM</div>
          <h2 className="mp-estate-card-line">{sim.msisdn}</h2>
          <div className="mp-estate-badge-row" style={{ marginTop: 10 }}>
            <span className="mp-group-chip mp-group-chip--ind"><Icon name="card-sim" size={11} />Other Network</span>
            <span>{sim.network}</span>
            <SimTypeBadge type={sim.sim_type} />
            <StatusBadge status={window.MP_REQ.estStatus(sim)} sim={sim} />
            {window.RequestRowChip ? <window.RequestRowChip sim={sim} /> : null}
          </div>
        </div>
      </div>
      <div className="mp-sim-cardfoot">
        <button type="button" className={"mp-sim-disclosure" + (open ? " is-open" : "")}
          onClick={() => setOpen((o) => !o)} aria-expanded={open}>
          <Icon name="chevron-down" size={16} />
          <span>{open ? "Hide" : "Show"} usage and full SIM details</span>
        </button>
        <a className="mp-glance-link" href={"#/sims/" + sim.id}>View further details <Icon name="arrow-right" size={15} /></a>
      </div>
      {open ?
      <div className="mp-sim-details">
        <div className="mp-estate-detail-grid">
          <AltNetUsageBlock sim={sim} />
          <div>
            <h4>SIM Card Information</h4>
            <div className="mp-kv-grid">
              <KvCell label="Assigned Number" value={sim.msisdn} />
              <KvCell label="Network" value={sim.network} />
              <KvCell label="Data Plan" value={plan.data} />
              <KvCell label="SIM Serial" value={sim.serial} />
              <KvCell label="SIM Type" value={sim.sim_type} />
            </div>
          </div>
        </div>
      </div> : null}
    </Card>);
}

/* Travel usage is live, so it reads like a UK SIM. */
function TravelUsageBlock({ sim }) {
  const r = travelRead(sim);
  if (r.awaiting) return (
    <div>
      <h4>Data Usage</h4>
      <Empty icon="info" title="No usage yet"
        message={"This plan has not been used. It runs for " + (r.plan.duration_days || 30) + " days from the first time data is used."} />
    </div>);
  const pct = Math.round(r.used / r.allowance_gb * 100);
  return (
    <div>
      <h4>Data Usage</h4>
      <p className="mp-card-head-sub" style={{ marginBottom: 12 }}>Current usage on {r.count > 1 ? "the plan ending soonest." : "this travel plan."}</p>
      <div className="mp-meter-track">
        <div className="mp-meter-fill" style={{ width: Math.min(100, pct) + "%" }} />
      </div>
      <div className="mp-meter-foot">
        <span><strong>{EST.estGb(r.used)} GB</strong> used of {r.allowance_gb} GB{r.expires ? "" : " this month"}</span>
        <span>{r.expires ? "Plan ends " + EST.fmtDate(r.expires) : "Renews " + EST.fmtDate(r.renews_on)}</span>
      </div>
      <div style={{ marginTop: 16 }}><AllowanceFlag sim={{ used: r.used, allowance_gb: r.allowance_gb }} /></div>
    </div>);
}

/* ---------- Plans on a travel eSIM ---------- */
function PlanStatusBadge({ state }) {
  const s = window.MP_TRAVEL.PLAN_STATUS[state];
  if (state === "active") return <Badge key="a" variant="ok" icon="circle-check">Active</Badge>;
  if (state === "expired") return <Badge key="e" variant="off" icon="circle-slash">Expired</Badge>;
  return <Badge key={state} variant="pending" icon="loader">{s.label}</Badge>;
}

function TravelPlansCard({ sim, onCancel }) {
  const TV2 = window.MP_TRAVEL;
  const rows = TV2.plansFor(sim.id);
  if (!rows.length) return null;
  return (
    <Card style={{ overflow: "hidden" }}>
      <div className="mp-card-head">
        <div>
          <h3>Plans</h3>
          <div className="mp-card-head-sub">Plans on this travel eSIM. Buying another plan adds it here.</div>
        </div>
        {MP_ALLOW("sim.order") ?
          <Button variant="secondary" size="sm" icon="plus" href="#/sims/travel/new">Add Another Plan</Button> : null}
      </div>
      <div className="mp-plan-rows">
        {rows.map((p) => {
          const state = TV2.planStatus(p);
          const ends = TV2.expiresAt(p);
          const canCancel = MP_ALLOW("sim.order") && p.type === "recurring" && state === "active";
          return (
            <div className="mp-plan-row" key={p.id}>
              <div className="mp-plan-row-main">
                <div className="mp-plan-row-top">
                  <span className="mp-plan-row-name">{p.allowance_gb} GB {TV2.areaLabel(p.area)}</span>
                  <PlanStatusBadge state={state} />
                  {p.premium && window.PremiumChip ? <window.PremiumChip /> : null}
                </div>
                <div className="mp-plan-row-sub">{p.type === "one_off" ?
                  (state === "awaiting" ? "Valid for " + (p.duration_days || 30) + " days from first use" :
                   state === "expired" ? "Ended " + EST.fmtDate(ends) : "Ends " + EST.fmtDate(ends)) :
                  (state === "not_renewing" ? "Will not renew. Active until " + EST.fmtDate(new Date(p.renews_on)) :
                   state === "expired" ? "Ended " + EST.fmtDate(new Date(p.renews_on)) :
                   "Renews " + EST.fmtDate(new Date(p.renews_on)) + " · " + p.term_months + " month term")}</div>
              </div>
              <div className="mp-plan-row-usage">{state === "awaiting" ? "No usage yet" :
                <><strong>{EST.estGb(p.used || 0)} GB</strong> of {p.allowance_gb} GB</>}</div>
              <div>{canCancel ?
                <ActionsMenu items={[{ label: "Cancel Renewal", onClick: () => onCancel(p) }]} /> :
                <ActionsMenu items={[{ note: "No actions for this plan." }]} />}</div>
            </div>);
        })}
      </div>
    </Card>);
}

function CancelRenewalModal({ plan, onClose, onConfirm }) {
  const end = EST.fmtDate(new Date(plan.renews_on));
  return (
    <div className="mp-modal-overlay" onClick={onClose}>
      <div className="mp-modal" onClick={(e) => e.stopPropagation()} style={{ maxWidth: 440 }}>
        <div className="mp-modal-ic mp-modal-ic--neutral"><Icon name="refresh-cw" size={20} /></div>
        <h3 className="mp-modal-title">Stop this plan renewing?</h3>
        <p className="mp-modal-sub">This plan will not renew. It remains active until <strong>{end}</strong>.</p>
        <div className="mp-modal-actions">
          <Button variant="secondary" onClick={onClose}>Keep Plan</Button>
          <Button variant="primary" icon="check" onClick={onConfirm}>Stop Renewal</Button>
        </div>
      </div>
    </div>);
}

function TravelSimDetail({ sim }) {
  const TV2 = window.MP_TRAVEL;
  TV2.useTravel();
  const r = travelRead(sim);
  const cov = { label: TV2.areaLabel(r.area || sim.coverage), countries: TV2.areaCountryCount(r.area || sim.coverage) };
  const user = estUser(sim);
  const [cancelling, setCancelling] = uE(null);
  const [open, setOpen] = uE(false);
  const ctx = window.useRoles ? window.useRoles() : null;
  window.MP_REQ.useRequests();
  const reqState = window.MP_REQ.openRequestFor(sim.id) || window.MP_REQ.noticeFor(sim.id);
  React.useEffect(() => { if (window.lucide) { try { window.lucide.createIcons(); } catch (e) {} } });
  React.useEffect(() => {
    let msg = null;
    try { msg = sessionStorage.getItem("mp-travel-toast"); sessionStorage.removeItem("mp-travel-toast"); } catch (e) {}
    if (msg && ctx) ctx.toast({ kind: "ok", title: "Plan added", body: msg });
  }, []);
  return (
    <>
      <PageHead title="SIM Management" />
      <BackLink href="#/sims?group=travel">Back to SIMs</BackLink>

      <Card>
        <div className="mp-sim-bar">
          <div>
            <div className="mp-pool-hero-eyebrow">Travel eSIM Details</div>
            <h2 className="mp-sim-hero-number">{cov.label}</h2>
            <div className="mp-estate-facts">
              {cov.countries > 1 ? <span>Covers {cov.countries} countries</span> : <span>Single country</span>}
              <span className="mp-dot-sep">•</span>
              <span>{r.type === "recurring" ? "Recurring" : "One-Off"}</span>
              {r.count > 1 ? <><span className="mp-dot-sep">•</span><span className="mp-plan-count">{r.count} plans on this eSIM</span></> : null}
              <span className="mp-dot-sep">•</span>
              <span className="mp-group-chip mp-group-chip--travel"><Icon name="plane" size={11} />Travel</span>
            </div>
            <div className="mp-sim-hero-meta" style={{ marginTop: 10 }}>
              {user ?
                <>
                  <Avatar initials={user.initials} size={26} tone="mist" />
                  <span>Assigned to <a href={"#/users/" + user.id} style={{ color: "var(--mp-pine)", fontWeight: 700, textDecoration: "underline" }}>{user.full_name}</a></span>
                </> :
                <span style={{ color: "var(--fg-3)" }}>Unassigned</span>}
              <span className="mp-dot-sep">•</span>
              <SimTypeBadge type={sim.sim_type} />
              <StatusBadge status={sim.status} sim={sim} />
            </div>
          </div>
        </div>
        {reqState ? <div className="mp-sim-banner-wrap"><window.RequestBanner sim={sim} /></div> : null}

        <button type="button" className={"mp-sim-disclosure" + (open ? " is-open" : "")}
          onClick={() => setOpen((o) => !o)} aria-expanded={open}>
          <Icon name="chevron-down" size={16} />
          <span>{open ? "Hide" : "Show"} usage and full SIM details</span>
        </button>

        {open ?
        <div className="mp-sim-details">
          <div className="mp-estate-detail-grid">
            <TravelUsageBlock sim={sim} />
            <div>
              <h4>eSIM Information</h4>
              <div className="mp-kv-grid">
                <KvCell label="Coverage" value={cov.label} />
                <KvCell label="Allowance" value={r.allowance_gb + " GB"} />
                <KvCell label="Plan Type" value={r.type === "recurring" ? "Recurring" : "One-Off"} />
                <KvCell label={r.expires ? "Plan Ends" : "Renews"} value={r.awaiting ? "On first use" : EST.fmtDate(r.expires || r.renews_on)} />
                <KvCell label="SIM Serial" value={sim.serial} />
                <KvCell label="SIM Type" value={sim.sim_type} />
              </div>
            </div>
          </div>
        </div> : null}
      </Card>

      {window.EsimInstallCard ? <window.EsimInstallCard sim={sim} /> : null}

      <TravelPlansCard sim={sim} onCancel={(p) => setCancelling(p)} />

      {cancelling ?
      <CancelRenewalModal plan={cancelling}
        onClose={() => setCancelling(null)}
        onConfirm={() => {
          TV2.cancelRenewal(cancelling.id);
          setCancelling(null);
          if (ctx) ctx.toast({ kind: "ok", title: "Renewal stopped", body: "This plan will not renew. It remains active until " + EST.fmtDate(new Date(cancelling.renews_on)) + "." });
        }} /> : null}

    </>);
}

/* Route by group; UK variants fall through to the existing page. */
function EstateSimShowPage({ id }) {
  const sim = EDATA.SIMS.find((s) => s.id === Number(id));
  if (sim && sim.group === "international") return <InternationalSimDetail key={sim.id} sim={sim} />;
  if (sim && sim.group === "travel") return <TravelSimDetail key={sim.id} sim={sim} />;
  if (sim && sim.group === "altnet") return <AltNetSimDetail key={sim.id} sim={sim} />;
  return <BaseSimShowPage id={id} />;
}

/* ---------- User page SIM card, group-aware ---------- */
function EstateUserSimCard({ sim }) {
  const intl = sim.group === "international";
  const [open, setOpen] = uE(false);
  window.MP_TRAVEL.useTravel();
  const tr = intl ? null : travelRead(sim);
  const cov = intl ? null : { label: window.MP_TRAVEL.areaLabel(tr.area || sim.coverage) };
  return (
    <Card style={{ overflow: "hidden" }}>
      <div className="mp-sim-bar">
        <div>
          <div className="mp-estate-card-kind">{intl ? "International SIM" : "Travel eSIM"}</div>
          <h2 className="mp-estate-card-line">{intl ? sim.msisdn : cov.label}</h2>
          <div className="mp-estate-badge-row" style={{ marginTop: 10 }}>
            {intl ?
              <>
                <span className="mp-group-chip mp-group-chip--intl"><Icon name="globe" size={11} />International</span>
                <CountryLabel code={sim.country} />
              </> :
              <>
                <span className="mp-group-chip mp-group-chip--travel"><Icon name="plane" size={11} />Travel</span>
                <ValidityCell summary={tr} />
              </>}
            <SimTypeBadge type={sim.sim_type} />
            <StatusBadge status={intl ? window.MP_REQ.estStatus(sim) : sim.status} sim={sim} />
            {intl && window.RequestRowChip ? <window.RequestRowChip sim={sim} /> : null}
          </div>
        </div>
      </div>
      <div className="mp-sim-cardfoot">
        <button type="button" className={"mp-sim-disclosure" + (open ? " is-open" : "")}
          onClick={() => setOpen((o) => !o)} aria-expanded={open}>
          <Icon name="chevron-down" size={16} />
          <span>{open ? "Hide" : "Show"} usage and full SIM details</span>
        </button>
        <a className="mp-glance-link" href={"#/sims/" + sim.id}>View further details <Icon name="arrow-right" size={15} /></a>
      </div>

      {open ?
      <div className="mp-sim-details">
        <div className="mp-estate-detail-grid">
          {intl ? <EstateUsageBlock sim={sim} /> : <TravelUsageBlock sim={sim} />}
          <div>
            <h4>{intl ? "SIM Card Information" : "eSIM Information"}</h4>
            <div className="mp-kv-grid">
              {intl ?
              <>
                <KvCell label="Local Number" value={sim.msisdn} />
                <KvCell label="Country" value={(EST.COUNTRIES[sim.country] || {}).name} />
                <KvCell label="Network" value={sim.network} />
                <KvCell label="Allowance" value={sim.allowance_gb + " GB"} />
              </> :
              <>
                <KvCell label="Coverage" value={cov.label} />
                <KvCell label="Allowance" value={tr.allowance_gb + " GB"} />
                <KvCell label="Plan Type" value={tr.type === "recurring" ? "Recurring" : "One-Off"} />
                <KvCell label={tr.expires ? "Plan Ends" : "Renews"} value={tr.awaiting ? "On first use" : EST.fmtDate(tr.expires || tr.renews_on)} />
              </>}
              <KvCell label="SIM Serial" value={sim.serial} />
              <KvCell label="SIM Type" value={sim.sim_type} />
            </div>
          </div>
        </div>
      </div> : null}
    </Card>);
}
function EstateUserSimCardRouter({ sim }) {
  if (sim.group === "altnet") return <AltNetUserSimCard sim={sim} />;
  if (sim.group === "international" || sim.group === "travel") return <EstateUserSimCard sim={sim} />;
  return <BaseUserSimCard sim={sim} />;
}

Object.assign(window, {
  SimShowPage: EstateSimShowPage, UserSimCard: EstateUserSimCardRouter, InternationalSimsPanel, TravelEsimsPanel,
  FreshnessStamp, AllowanceFlag, CountryLabel, CountryTile
});
