/* ========================================================================
   esim-install.jsx — eSIM install lifecycle (Story 3)
   Every eSIM carries an install state, separate from SIM status:
   ready (Ready to Install) → installed. The platform cannot see a scan, so
   installation is confirmed when the first mobile data arrives. A consumed
   QR is never shown again.
   ======================================================================== */
const { useState: uI, useEffect: eI } = React;
const ID = window.MILO_DATA;

const INSTALL_KEY = "mp_esim_install_v1";
let INST = { states: {}, installedAt: {}, emailAt: {} };
try { const raw = localStorage.getItem(INSTALL_KEY); if (raw) INST = { ...INST, ...JSON.parse(raw) }; } catch (e) {}
const instSubs = new Set();
function instNotify() {
  try { localStorage.setItem(INSTALL_KEY, JSON.stringify(INST)); } catch (e) {}
  instSubs.forEach((cb) => cb());
}
function useInstall() {
  const [, force] = uI(0);
  eI(() => { const cb = () => force((n) => n + 1); instSubs.add(cb); return () => instSubs.delete(cb); }, []);
  return INST;
}

/* ---------- State model ----------
   Existing estates map by status: an eSIM waiting to be set up is ready,
   an eSIM already carrying traffic is installed. Physical and IoT SIMs have
   no install state at all. */
function baseInstallState(sim) {
  if (!sim || sim.sim_type !== "eSIM") return null;
  if (sim.install_state) return sim.install_state;
  if (sim.status === "Activated" || sim.status === "For Activation") return "ready";
  return "installed";
}
function installState(sim) {
  const base = baseInstallState(sim);
  if (!base) return null;
  return INST.states[sim.id] || base;
}
const isReady = (sim) => installState(sim) === "ready";
const isInstalled = (sim) => installState(sim) === "installed";
/* A SIM has one visible status. While an eSIM is waiting to be set up that
   status is Ready to Install, whatever the underlying record says, so no SIM
   ever reads Active above a Ready to Install section. */
function displayStatus(sim, status) {
  return isReady(sim) ? "Ready to Install" : status;
}

/* Deterministic stand-in confirmation time for eSIMs installed before now. */
function seedTime(sim) {
  let h = 0;
  const seed = String(sim.id) + (sim.serial || "");
  for (let i = 0; i < seed.length; i++) { h = h * 31 + seed.charCodeAt(i) >>> 0; }
  const hh = 8 + h % 11, mm = h % 60;
  return String(hh).padStart(2, "0") + ":" + String(mm).padStart(2, "0");
}
const fmtLong = (d) => d.toLocaleDateString("en-GB", { day: "numeric", month: "long", year: "numeric" });
/* The date this eSIM entered service, whichever field the group records it in. */
function seedDate(sim) {
  if (sim.activation_date) return new Date(sim.activation_date + "T00:00:00");
  if (sim.provisioned) return new Date(sim.provisioned);
  return null;
}
function emailLabel(sim) {
  const iso = INST.emailAt[sim.id];
  if (iso) return fmtLong(new Date(iso));
  const base = seedDate(sim);
  return base ? fmtLong(base) : null;
}

/* Generic setup details, the text alternative to the QR. */
function manualDetails(sim) {
  let h = 0;
  const seed = (sim.serial || "") + String(sim.id);
  for (let i = 0; i < seed.length; i++) { h = h * 33 + seed.charCodeAt(i) >>> 0; }
  const block = (n) => String((h >> n & 0xffff).toString(16)).toUpperCase().padStart(4, "0");
  return {
    address: "esim.meaningfulplanet.co.uk",
    code: "MP-" + block(0) + "-" + block(4) + "-" + block(8)
  };
}

/* ---------- Transitions ---------- */
function sendActivationEmail(simId) {
  INST.emailAt[simId] = new Date().toISOString();
  instNotify();
}
function confirmInstall(simId) {
  const sim = ID.SIMS.find((s) => s.id === simId);
  if (!sim) return false;
  INST.states[simId] = "installed";
  INST.installedAt[simId] = new Date().toISOString();
  const who = ID.USERS.find((u) => u.sim_ids.includes(simId));
  ID.ALERTS.unshift({
    id: Date.now(), kind: "esim_installed", title: "eSIM installed and confirmed",
    description: "First mobile data has arrived, so the eSIM for " + (who ? who.full_name : sim.msisdn) + " is confirmed as installed.",
    time_ago: "Just now"
  });
  instNotify();
  return true;
}
/* Tweaks: confirm the first eSIM still waiting to be set up. */
function confirmFirstReady() {
  const sim = ID.SIMS.find((s) => isReady(s));
  return sim ? confirmInstall(sim.id) : false;
}
/* A completed device move consumes the old credentials and starts again. */
function moveCompleted(simId) {
  INST.states[simId] = "ready";
  delete INST.installedAt[simId];
  INST.emailAt[simId] = new Date().toISOString();
  instNotify();
}

/* ---------- Install section ---------- */
function EsimInstallCard({ sim }) {
  useInstall();
  window.MP_REQ.useRequests();
  const ctx = window.useRoles ? window.useRoles() : null;
  const state = installState(sim);
  if (!state) return null;
  const canManage = MP_ALLOW("sim.manage");
  const user = ID.USERS.find((u) => u.sim_ids.includes(sim.id)) || null;
  const details = manualDetails(sim);
  const sent = emailLabel(sim);

  /* Installed eSIMs show nothing: the activation date already carries this,
     and the QR is consumed. */
  if (state === "installed") return null;

  return (
    <Card>
      <div className="mp-card-head">
        <div>
          <h3>Install This eSIM</h3>
          <div className="mp-card-head-sub">
            {canManage ?
              "Scan this code on the device that will use the eSIM." :
              "This eSIM is ready to install. Your account administrators hold the setup details."}
          </div>
        </div>
        <span className="mp-install-badge"><Icon name="qr-code" size={13} />Ready to Install</span>
      </div>

      {canManage ?
      <div className="mp-card-body">
        <div className="mp-install-grid">
          <div className="mp-install-qr">
            <FakeQR />
            <p className="mp-install-once">This code works once. Scan it on the device that will use the eSIM.</p>
          </div>
          <div className="mp-install-copy">
            <p className="mp-install-note">Once installed, the platform confirms the connection, usually within 30 minutes of setup.</p>
            {user ?
            <div className="mp-install-receipt">
              <div className="mp-install-receipt-text">
                <Icon name="mail" size={15} />
                <span>Activation email sent to <strong>{user.full_name}</strong>{sent ? ", " + sent : ""}</span>
              </div>
              <Button variant="secondary" size="sm" icon="send"
                onClick={() => {
                  sendActivationEmail(sim.id);
                  if (ctx) ctx.toast({ kind: "ok", title: "Activation email sent", body: "A fresh copy is on its way to " + user.email + "." });
                }}>Resend Activation Email</Button>
            </div> :
            <p className="mp-field-help">Assign a user to send them the activation email. You can also install now using the QR code.</p>}
          </div>
        </div>
        <Collapsible title="Can't scan? Enter these details manually" icon="pencil">
          <p className="mp-field-help" style={{ marginBottom: 12 }}>Enter these in the device's mobile data settings, where it asks to add an eSIM manually.</p>
          <div className="mp-kv-grid">
            <KvCell label="Setup Address" value={details.address} />
            <KvCell label="Activation Code" value={details.code} />
          </div>
        </Collapsible>
      </div> :
      <div className="mp-card-body">
        <p className="mp-install-note">Once installed, the platform confirms the connection, usually within 30 minutes of setup.</p>
      </div>}
    </Card>);
}

window.MP_ESIM = {
  useInstall, installState, isReady, isInstalled, displayStatus, emailLabel,
  sendActivationEmail, confirmInstall, confirmFirstReady, moveCompleted
};
Object.assign(window, { EsimInstallCard });
