"""The window a non-technical person sees when they double-click the helper.

It is a web page, not a native dialog, for one reason: it has to look and behave
the same on Windows, macOS and Linux, and every one of those already has a
browser. A native toolkit would mean tkinter — an extra system package on Linux
and a signing headache on macOS — for a screen with four buttons on it.
"""

SETUP_HTML = r"""<!doctype html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Astitvaams Printer Setup</title>
<style>
  :root { color-scheme: light; --line:#e2e8f0; --ink:#0b1c30; --muted:#64748b;
          --brand:#0F4C81; --ok:#059669; --bad:#dc2626; }
  * { box-sizing:border-box }
  body { margin:0; font:15px/1.5 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
         background:#f5f7fa; color:var(--ink); display:flex; justify-content:center;
         padding:32px 16px }
  .card { width:100%; max-width:560px; background:#fff; border:1px solid var(--line);
          border-radius:16px; padding:28px; box-shadow:0 1px 3px rgba(0,0,0,.06) }
  h1 { font-size:20px; margin:0 0 4px }
  p.sub { color:var(--muted); margin:0 0 24px; font-size:13px }
  .step { border-top:1px solid var(--line); padding:18px 0 }
  .step:first-of-type { border-top:0; padding-top:0 }
  .step h2 { font-size:14px; margin:0 0 8px; display:flex; align-items:center; gap:8px }
  .n { width:22px;height:22px;border-radius:99px;background:var(--brand);color:#fff;
       font-size:12px;display:grid;place-items:center;flex:none }
  input[type=text] { width:100%; height:42px; padding:0 12px; font-size:15px;
                     border:1px solid #cbd5e1; border-radius:10px }
  button { height:42px; padding:0 18px; font-size:14px; font-weight:600; cursor:pointer;
           border-radius:10px; border:1px solid var(--brand); background:var(--brand); color:#fff }
  button.ghost { background:#fff; color:var(--brand) }
  button:disabled { opacity:.5; cursor:default }
  .row { display:flex; gap:10px; align-items:center; flex-wrap:wrap }
  .msg { margin-top:10px; font-size:13px; padding:10px 12px; border-radius:10px; display:none }
  .msg.ok  { display:block; background:#ecfdf5; color:var(--ok); border:1px solid #a7f3d0 }
  .msg.bad { display:block; background:#fef2f2; color:var(--bad); border:1px solid #fecaca }
  .msg.info{ display:block; background:#f1f5f9; color:var(--muted); border:1px solid var(--line) }
  .done { text-align:center; padding:8px 0 }
  .done .tick { font-size:40px; color:var(--ok) }
  code { background:#f1f5f9; padding:1px 5px; border-radius:5px; font-size:12px }
</style>
<div class="card">
  <h1>Astitvaams Printer Setup</h1>
  <p class="sub">Three steps. You can close this page when it says finished.</p>

  <div class="step">
    <h2><span class="n">1</span> Your Astitvaams address</h2>
    <div class="row">
      <input type="text" id="site" placeholder="https://aams.yourcompany.com" style="flex:1;min-width:240px">
      <button class="ghost" id="saveBtn">Save</button>
    </div>
    <div class="msg" id="siteMsg"></div>
  </div>

  <div class="step">
    <h2><span class="n">2</span> Find your printer</h2>
    <div class="row">
      <button class="ghost" id="findBtn">Find my printer</button>
      <span id="printerName" style="color:var(--muted);font-size:13px"></span>
    </div>
    <div class="msg" id="findMsg"></div>
  </div>

  <div class="step">
    <h2><span class="n">3</span> Print a test label</h2>
    <div class="row">
      <button id="testBtn" disabled>Print test label</button>
      <!-- The roll is configured in ONE place: Astitvaams > Label Workspace >
           Printers. Shown here as a fact, not as a second setting, so the test
           label cannot disagree with a real one. The dropdown appears only when
           Astitvaams has no printer registered at all. -->
      <span id="rollFixed" style="font-size:13px;color:var(--ink)"></span>
      <label id="rollPick" style="display:none;font-size:13px;color:var(--muted)">
        Roll type
        <select id="roll" style="height:38px;border:1px solid #cbd5e1;border-radius:8px;padding:0 8px;margin-left:6px"></select>
      </label>
    </div>
    <div id="rollHint" style="margin-top:8px;font-size:12px;color:var(--muted)"></div>
    <div class="msg" id="testMsg"></div>
  </div>

  <div class="step" id="finishStep">
    <div class="row">
      <button id="finishBtn">Finish &amp; start automatically</button>
    </div>
    <div class="msg" id="finishMsg"></div>
  </div>
</div>
<script>
let printerIp = null;
const $ = (id) => document.getElementById(id);
const say = (el, kind, text) => { el.className = "msg " + kind; el.textContent = text; };

async function api(path, body) {
  const r = await fetch(path, body ? {
    method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body),
  } : {});
  return r.json();
}

// A saved address is the single thing that makes Astitvaams able to talk to this
// helper. Without it everything below still works — find the printer, print a
// test label — and Astitvaams still says "Not installed on this computer", because
// the browser blocks the call before it arrives. So say so, in step 1, in red.
fetch("/setup/state").then(r => r.json()).then(s => {
  registeredRoll = s.label_size || "";
  showRoll("");
  if (s.site) {
    $("site").value = s.site;
    say($("siteMsg"), "ok", "Saved - " + s.site);
  } else {
    say($("siteMsg"), "bad",
        "Not set yet. Type the address you use to open Astitvaams (copy it from the "
      + "browser bar of the Astitvaams tab) and press Save. Until you do, Astitvaams will "
      + "keep saying the helper is not installed.");
  }
});

$("saveBtn").onclick = async () => {
  const site = $("site").value.trim();
  if (!site) { say($("siteMsg"), "bad", "Type your Astitvaams address first."); return; }
  const r = await api("/setup/site", { site });
  if (r.ok) say($("siteMsg"), "ok", "Saved — " + r.saved);
  else say($("siteMsg"), "bad", r.error || "Could not save that address.");
};

$("findBtn").onclick = async () => {
  $("findBtn").disabled = true;
  say($("findMsg"), "info", "Looking on your network… this takes a few seconds.");
  try {
    const r = await api("/discover");
    if (r.ok && r.printers.length) {
      const p = r.printers[0];
      printerIp = p.ip;
      $("printerName").textContent = p.name + "  ·  " + printerIp
        + (p.roll ? "  ·  " + p.roll + " roll" : "");
      if (p.errors && p.errors.length) {
        say($("findMsg"), "bad", "Found it, but: " + p.errors.join("; "));
      } else if (p.roll) {
        say($("findMsg"), "ok", "Found your printer. It has a " + p.roll + " roll in it.");
      } else {
        say($("findMsg"), "ok",
            "Found your printer. It did not say which roll is loaded — pick the "
          + "size below if the test label comes out wrong.");
      }
      await showRoll(p.label || "");
      $("testBtn").disabled = false;
    } else {
      say($("findMsg"), "bad", "No printer found. Check it is switched on and on the same Wi-Fi as this computer.");
    }
  } catch (e) { say($("findMsg"), "bad", "Could not search: " + e); }
  $("findBtn").disabled = false;
};

// The roll Astitvaams has registered for this printer. Sent in the download, so
// it is known before a printer is even found.
let registeredRoll = "";

async function loadRollChoices() {
  const el = $("roll");
  if (el.options.length) return;
  const r = await api("/setup/rolls", {});
  for (const roll of (r.rolls || [])) {
    const o = document.createElement("option");
    o.value = roll.id; o.textContent = roll.name || roll.id;
    el.appendChild(o);
  }
}

/** Show the roll that WILL be used, and where it came from. `reported` is what
 *  the printer says, used only to confirm or to warn — never to override. */
async function showRoll(reported) {
  if (registeredRoll) {
    $("rollFixed").textContent = "Roll: " + registeredRoll;
    $("rollPick").style.display = "none";
    if (reported && reported !== registeredRoll) {
      $("rollHint").innerHTML =
        "<b>Astitvaams has this printer set to " + registeredRoll + ", but the printer "
      + "has " + reported + " in it.</b> Load the " + registeredRoll + " roll, or change "
      + "it in Astitvaams &rsaquo; Label Workspace &rsaquo; Printers.";
    } else {
      $("rollHint").textContent =
        "Set in Astitvaams \u203a Label Workspace \u203a Printers"
        + (reported ? " and confirmed by the printer." : ". Change it there, not here.");
    }
    return;
  }
  // Nothing registered in Astitvaams. Only now is this a choice.
  await loadRollChoices();
  $("rollFixed").textContent = "";
  $("rollPick").style.display = "";
  if (reported) $("roll").value = reported;
  $("rollHint").textContent = reported
    ? "No printer is registered in Astitvaams, so this is read from the printer. "
      + "Add the printer in Label Workspace \u203a Printers to set it properly."
    : "No printer is registered in Astitvaams and the printer did not report a roll. "
      + "Pick the size that is loaded.";
}

$("testBtn").onclick = async () => {
  $("testBtn").disabled = true;
  say($("testMsg"), "info", "Sending…");
  // Only send a roll when Astitvaams has none. Otherwise the helper uses the
  // registered one, so this page cannot become a second place to set it.
  const override = registeredRoll ? undefined : $("roll").value;
  const r = await api("/setup/test-print", { ip: printerIp, label: override });
  if (r.ok) {
    say($("testMsg"), (r.guessed || r.mismatch) ? "info" : "ok",
        "Sent on the " + (r.label || "") + " roll. "
      + "A label should come out of the printer now."
      + (r.note ? " " + r.note : ""));
    if (r.mismatch || r.guessed) await showRoll(r.reported || "");
  } else {
    // The helper now sends the printer's own reason - open cover, wrong roll,
    // empty roll. Show it as-is; "The printer refused it" helps nobody.
    say($("testMsg"), "bad", r.error || "The printer refused it.");
    // A roll disagreement is refused, not printed. Put both sizes back in the
    // hint line so the fix is visible next to the roll it applies to.
    if (r.mismatch) await showRoll(r.reported || "");
  }
  $("testBtn").disabled = false;
};

$("finishBtn").onclick = async () => {
  if (!$("site").value.trim()) {
    say($("finishMsg"), "bad",
        "Fill in step 1 first - without your Astitvaams address, Astitvaams cannot use this helper.");
    return;
  }
  $("finishBtn").disabled = true;
  say($("finishMsg"), "info", "Setting up…");
  const r = await api("/setup/install", {});
  if (r.ok) {
    document.querySelector(".card").innerHTML =
      '<div class="done"><div class="tick">&#10003;</div>' +
      '<h1>All set</h1><p class="sub">The helper now starts on its own when you turn this computer on.<br>' +
      'You can close this page and go back to Astitvaams.' +
      // Says so when it had to fall back to the Startup folder, rather than
      // reporting the same "All set" for two different outcomes.
      (r.note ? '<br><br>' + r.note : '') + '</p></div>';
  } else {
    say($("finishMsg"), "bad", r.error || "Could not set it to start automatically.");
    $("finishBtn").disabled = false;
  }
};
</script>
"""
