/* ========================================================================
   csv-ui.jsx — Upload, validation report and batch surfaces (Story 6)
   One upload component and one report pattern, used by CSV assignment and
   Import Users. Loads after csv-batch.jsx.
   ======================================================================== */
const { useState: uU, useRef: rU } = React;
const BATCH = window.MP_BATCH;
const UD = window.MILO_DATA;

/* ---------- Drag and drop upload zone ---------- */
function UploadZone({ onFile, filename }) {
  const [over, setOver] = uU(false);
  const input = rU(null);
  const take = (file) => {
    if (!file) return;
    const reader = new FileReader();
    reader.onload = () => onFile(file.name, String(reader.result));
    reader.readAsText(file);
  };
  return (
    <div className={"mp-drop" + (over ? " is-over" : "")}
      onDragOver={(e) => { e.preventDefault(); setOver(true); }}
      onDragLeave={() => setOver(false)}
      onDrop={(e) => { e.preventDefault(); setOver(false); take(e.dataTransfer.files[0]); }}
      onClick={() => input.current && input.current.click()}
      role="button" tabIndex={0}
      onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); input.current.click(); } }}>
      <input ref={input} type="file" accept=".csv,text/csv" hidden
        onChange={(e) => { take(e.target.files[0]); e.target.value = ""; }} />
      <div className="mp-drop-ic"><Icon name="upload" size={22} /></div>
      <div className="mp-drop-title">{filename || "Drop your CSV file here"}</div>
      <div className="mp-drop-msg">{filename ? "Choose a different file" : "Or click to choose a file from your computer"}</div>
    </div>);
}

/* ---------- Validation report ---------- */
const BUCKETS = [
  { id: "ready", label: "Ready", icon: "circle-check", tone: "ok" },
  { id: "warnings", label: "Warnings", icon: "info", tone: "info" },
  { id: "blocked", label: "Blocked", icon: "triangle-alert", tone: "warn" }];

function ReportBucket({ bucket, rows, kind, open, onToggle }) {
  if (!rows.length) return null;
  return (
    <div className={"mp-bucket mp-bucket--" + bucket.tone}>
      <button type="button" className="mp-bucket-head" onClick={onToggle} aria-expanded={open}>
        <span className="mp-bucket-ic"><Icon name={bucket.icon} size={15} /></span>
        <span className="mp-bucket-count">{rows.length}</span>
        <span className="mp-bucket-label">{bucket.label}</span>
        <span className="mp-bucket-sub">{
          bucket.id === "ready" ? (kind === "import" ? "Will be added" : "Will be assigned") :
          bucket.id === "warnings" ? (kind === "import" ? "Already on your user list, so these rows are skipped" : "Will be submitted, with something to know") :
          "These rows are skipped. Fix them and upload the file again."}</span>
        <Icon name={open ? "chevron-up" : "chevron-down"} size={15} />
      </button>
      {open ?
      <div className="mp-bucket-rows">
        {rows.map((r) =>
          <div className="mp-bucket-row" key={r.line}>
            <span className="mp-bucket-line">Row {r.line}</span>
            <span className="mp-bucket-who">
              {r.full_name || <em>No name</em>}
              {r.sim_serial ? <span className="mp-bucket-serial mp-mono">{r.sim_serial}</span> : null}
            </span>
            <span className="mp-bucket-reason">{r.reason || r.email}</span>
          </div>)}
      </div> : null}
    </div>);
}

function ValidationReport({ report }) {
  const [open, setOpen] = uU({ blocked: true, warnings: false, ready: false });
  return (
    <div className="mp-report">
      {report.extra && report.extra.length ?
      <div className="mp-wiz-note">
        <Icon name="info" size={15} />
        <span>We ignored {report.extra.length === 1 ? "the column" : "the columns"} {report.extra.map((c) => "\u201c" + c + "\u201d").join(", ")}, which the template does not use.</span>
      </div> : null}
      {BUCKETS.map((b) =>
        <ReportBucket key={b.id} bucket={b} rows={report[b.id]} kind={report.kind}
          open={!!open[b.id]} onToggle={() => setOpen({ ...open, [b.id]: !open[b.id] })} />)}
    </div>);
}

/* ---------- Confirmation ---------- */
function BatchConfirmModal({ kind, count, blocked, onClose, onConfirm }) {
  const assign = kind === "assign";
  return (
    <div className="mp-modal-overlay" onClick={onClose}>
      <div className="mp-modal" onClick={(e) => e.stopPropagation()} style={{ maxWidth: 470 }}>
        <div className="mp-modal-ic mp-modal-ic--neutral"><Icon name="upload" size={20} /></div>
        <h3 className="mp-modal-title">{assign ? "Submit " + count + " assignment" + (count === 1 ? "" : "s") + "?" : "Add " + count + " user" + (count === 1 ? "" : "s") + "?"}</h3>
        {blocked ? <p className="mp-modal-sub"><strong>{blocked} blocked row{blocked === 1 ? "" : "s"} will be skipped.</strong></p> : null}
        <p className="mp-modal-sub">{assign ? BATCH.SERVICE_WINDOW :
          "They are added straight away as standard users with no access to the platform. Assigning SIMs is a separate step."}</p>
        <div className="mp-modal-actions">
          <Button variant="secondary" onClick={onClose}>Cancel</Button>
          <Button variant="primary" onClick={onConfirm}>{assign ? "Submit Assignments" : "Add Users"}</Button>
        </div>
      </div>
    </div>);
}

/* ---------- Submitted state ---------- */
function BatchSubmitted({ batch }) {
  const assign = batch.kind === "assign";
  return (
    <Card>
      <div className="mp-batch-done">
        <div className="mp-batch-done-ic"><Icon name={assign ? "loader" : "circle-check"} size={24} /></div>
        <h3 className="mp-batch-done-title">{assign ?
          batch.rows.length + " assignment" + (batch.rows.length === 1 ? "" : "s") + " submitted" :
          batch.rows.length + " user" + (batch.rows.length === 1 ? "" : "s") + " added"}</h3>
        <p className="mp-batch-done-msg">{assign ? BATCH.SERVICE_WINDOW :
          "They are on your user list now. Assign them a SIM whenever you are ready."}</p>
        <div className="mp-batch-ref">Batch reference <a className="mp-ticket-ref mp-mono" href="#/support/tickets">{batch.ref}</a></div>
        <div className="mp-batch-done-cta">
          {assign ?
            <Button variant="secondary" icon="card-sim" href="#/sims">Back to SIM Management</Button> :
            <Button variant="secondary" icon="users" href="#/users">Back to User Management</Button>}
        </div>
      </div>
    </Card>);
}

/* ---------- The upload page, shared by both flows ---------- */
function CsvUploadPage({ kind, scopeIds, title, subtitle, back, backLabel }) {
  BATCH.useBatches();
  const [filename, setFilename] = uU(null);
  const [report, setReport] = uU(null);
  const [confirming, setConfirming] = uU(false);
  const [batch, setBatch] = uU(null);
  React.useEffect(() => { if (window.lucide) { try { window.lucide.createIcons(); } catch (e) {} } });

  if (batch) return (
    <>
      <PageHead title={title} />
      <BackLink href={back}>{backLabel}</BackLink>
      <BatchSubmitted batch={batch} />
    </>);

  const rows = report && !report.fatal ? BATCH.submittable(report) : [];
  const cols = BATCH.TEMPLATES[kind].columns;

  return (
    <>
      <PageHead title={title} subtitle={subtitle} />
      <BackLink href={back}>{backLabel}</BackLink>

      <Card style={{ maxWidth: 900 }}>
        <div className="mp-card-body">
          <div className="mp-csv-head">
            <div>
              <h4 className="mp-csv-h">Start from the Template</h4>
              <p className="mp-csv-p">One row per {kind === "assign" ? "SIM" : "person"}. The columns are {cols.map((c) => "\u201c" + c + "\u201d").join(", ")}.</p>
            </div>
            <div className="mp-csv-head-cta">
              <Button variant="secondary" size="sm" icon="download" onClick={() => BATCH.downloadTemplate(kind)}>Download Template</Button>
              <Button variant="secondary" size="sm" icon="download" onClick={() => BATCH.downloadSample(kind, scopeIds)}>Download Filled Example</Button>
            </div>
          </div>

          <UploadZone filename={filename}
            onFile={(name, text) => { setFilename(name); setReport(BATCH.validate(kind, text, scopeIds)); }} />

          {report && report.fatal ?
          <div className="mp-wiz-note mp-wiz-note--warn" style={{ marginTop: 18 }}>
            <Icon name="triangle-alert" size={15} />
            <span>{report.fatal}{report.hint ? " " + report.hint : ""}</span>
          </div> : null}

          {report && !report.fatal ?
          <>
            <ValidationReport report={report} />
            <div className="mp-csv-foot">
              <Button variant="secondary" href={back}>Cancel</Button>
              <Button variant="primary" className={rows.length ? "" : "is-disabled"}
                onClick={rows.length ? () => setConfirming(true) : undefined}>
                {kind === "assign" ? "Submit " + rows.length + " Assignment" + (rows.length === 1 ? "" : "s") :
                  "Add " + rows.length + " User" + (rows.length === 1 ? "" : "s")}
              </Button>
            </div>
          </> : null}
        </div>
      </Card>

      {confirming ?
      <BatchConfirmModal kind={kind} count={rows.length} blocked={report.blocked.length}
        onClose={() => setConfirming(false)}
        onConfirm={() => {
          const b = BATCH.submitBatch(kind, rows);
          /* Import touches no SIMs, so it completes at once — and the rows
             have to reach the users store, or the list never changes. */
          if (kind === "import") {
            if (window.MP_USERS) window.MP_USERS.createUsers(rows.filter((r) => r.state === "ready"));
            BATCH.fulfilBatch(b.id, 0);
          }
          setConfirming(false);
          setBatch(BATCH.batchById(b.id));
        }} /> : null}
    </>);
}

function AssignFromCsvPage() {
  const raw = (location.hash.split("?")[1] || "").match(/sims=([\d,]+)/);
  const scopeIds = raw ? raw[1].split(",").map(Number) : null;
  return (
    <CsvUploadPage kind="assign" scopeIds={scopeIds}
      title="Assign SIMs from a File"
      subtitle={scopeIds ?
        "Get " + scopeIds.length + " selected SIM" + (scopeIds.length === 1 ? "" : "s") + " to the right people in one upload. Anyone not on your user list yet is created for you." :
        "Get a batch of UK and IoT SIMs to the right people in one upload. Anyone not on your user list yet is created for you."}
      back="#/sims" backLabel="Back to SIMs" />);
}
function ImportUsersPage() {
  return (
    <CsvUploadPage kind="import"
      title="Import Users"
      subtitle="Add people to your account in bulk, so you can assign them SIMs. They are set up as standard users with no access to the platform."
      back="#/users" backLabel="Back to Users" />);
}

/* ---------- Waiting state on a SIM ---------- */
function AssignmentPendingChip({ sim }) {
  BATCH.useBatches();
  const p = BATCH.pendingAssignment(sim.id);
  if (!p) return null;
  return <span className="mp-req-chip"><Icon name="loader" size={11} />Assignment in progress</span>;
}
function AssignmentPendingBanner({ sim }) {
  BATCH.useBatches();
  const p = BATCH.pendingAssignment(sim.id);
  if (!p) return null;
  return (
    <div className="mp-req-banner">
      <Icon name="loader" size={17} />
      <div className="mp-batch-banner-body">
        <strong>Assignment in progress</strong>
        <span>This SIM will be assigned to {p.row.full_name}. {BATCH.SERVICE_WINDOW} Batch {p.batch.ref}.</span>
      </div>
    </div>);
}

/* ---------- Per-line results, opened from the completion alert ---------- */
function BatchResultsModal({ batch, onClose }) {
  const done = batch.rows.filter((r) => r.state === "done");
  const failed = batch.rows.filter((r) => r.state === "failed");
  const ctx = window.useRoles ? window.useRoles() : null;
  return (
    <div className="mp-modal-overlay" onClick={onClose}>
      <div className="mp-modal" onClick={(e) => e.stopPropagation()} style={{ maxWidth: 500 }}>
        <div className={"mp-modal-ic " + (failed.length ? "mp-modal-ic--clay" : "mp-modal-ic--mint")}>
          <Icon name={failed.length ? "triangle-alert" : "circle-check"} size={20} />
        </div>
        <h3 className="mp-modal-title">{done.length} {batch.kind === "import" ? "added" : "assigned"}{failed.length ? " · " + failed.length + " failed" : ""}</h3>
        <p className="mp-modal-sub">Batch {batch.ref}.</p>
        {failed.length ?
        <ul className="mp-fail-list">
          {failed.map((r) =>
            <li key={r.line}>
              <span>{r.full_name}{r.sim_serial ? <span className="mp-mono mp-bucket-serial-inline">{r.sim_serial}</span> : null}</span>
              <span>{r.reason}</span>
            </li>)}
        </ul> : null}
        <div className="mp-modal-actions">
          <Button variant="secondary" onClick={onClose}>Close</Button>
          {failed.length ?
          <Button variant="primary" icon="rotate-ccw" onClick={() => {
            const b = BATCH.submitBatch(batch.kind, failed.map((r) => ({ ...r, state: "ready", reason: null })));
            onClose();
            if (ctx) ctx.toast({ kind: "ok", title: "Resubmitted", body: failed.length + " row" + (failed.length === 1 ? "" : "s") + " submitted again as batch " + b.ref + "." });
          }}>Retry Failed</Button> : null}
        </div>
      </div>
    </div>);
}

Object.assign(window, {
  AssignFromCsvPage, ImportUsersPage, AssignmentPendingChip, AssignmentPendingBanner, BatchResultsModal
});
