<script lang="ts">
  import { onMount } from "svelte";
  import { push } from "svelte-spa-router";
  import { bytesToHex } from "@noble/hashes/utils";
  import {
    generateIdentity,
    signRegistration,
    type Ed25519Identity,
  } from "../lib/kez.js";
  import { register, healthz, ApiError } from "../lib/api.js";
  import { saveIdentity } from "../lib/identity-store.js";
  import { session } from "../lib/store.svelte.js";

  let step = $state<"handle" | "seed" | "confirm" | "submitting" | "done">("handle");

  let handle = $state("");
  let passphrase = $state("");
  let passphrase2 = $state("");

  let serverInfo = $state<{ server: string; version: string } | null>(null);
  let id = $state<Ed25519Identity | null>(null);
  let seedHex = $state("");
  let seedAck = $state(false);

  let error = $state<string | null>(null);
  let working = $state(false);

  onMount(async () => {
    try {
      const h = await healthz();
      serverInfo = { server: h.server, version: h.version };
    } catch {
      serverInfo = null;
    }
  });

  function validateHandleClient(h: string): string | null {
    if (h.length < 3) return "Handle must be at least 3 characters.";
    if (h.length > 32) return "Handle must be at most 32 characters.";
    if (!/^[a-z0-9][a-z0-9_-]*$/.test(h))
      return "Handle must be lowercase letters/digits/underscore/dash, starting with a letter or digit.";
    return null;
  }

  function goToSeedStep() {
    error = null;
    const v = validateHandleClient(handle);
    if (v) { error = v; return; }
    if (passphrase.length < 8) { error = "Passphrase must be at least 8 characters."; return; }
    if (passphrase !== passphrase2) { error = "Passphrases don't match."; return; }
    id = generateIdentity();
    seedHex = bytesToHex(id.seed);
    step = "seed";
  }

  async function submitRegistration() {
    if (!id || !serverInfo) return;
    working = true;
    error = null;
    step = "submitting";
    try {
      const signed = signRegistration(id, handle, serverInfo.server);
      const resp = await register(signed);
      await saveIdentity({
        handle: resp.handle,
        server: serverInfo.server,
        primary: id.identity,
        seed: id.seed,
        passphrase,
      });
      session.setUnlocked({
        handle: resp.handle,
        server: serverInfo.server,
        primary: id.identity,
        seed: id.seed,
      });
      step = "done";
    } catch (e) {
      step = "confirm";
      if (e instanceof ApiError) {
        error = `${e.code ?? "error"}: ${e.message}`;
      } else {
        error = (e as Error).message;
      }
    } finally {
      working = false;
    }
  }

  function copyToClipboard(s: string) {
    navigator.clipboard.writeText(s).catch(() => {});
  }
</script>

<div class="space-y-6">
  <h1 class="text-2xl font-bold text-text">Create account</h1>

  {#if !serverInfo}
    <p class="text-sm text-warning bg-warning/10 border border-warning/40 rounded p-3">
      Couldn't reach the chat server. Try refreshing.
    </p>
  {/if}

  <!-- Stepper -->
  <ol class="flex gap-2 text-xs text-text-muted">
    <li class={step === "handle" ? "font-semibold text-text" : ""}>1. Handle</li>
    <li>→</li>
    <li class={step === "seed" ? "font-semibold text-text" : ""}>2. Back up seed</li>
    <li>→</li>
    <li class={step === "confirm" || step === "submitting" ? "font-semibold text-text" : ""}>3. Confirm</li>
    <li>→</li>
    <li class={step === "done" ? "font-semibold text-text" : ""}>4. Done</li>
  </ol>

  {#if error}
    <p class="text-sm text-danger bg-danger/10 border border-danger/40 rounded p-3">
      {error}
    </p>
  {/if}

  {#if step === "handle"}
    <form
      class="space-y-4"
      onsubmit={(e) => { e.preventDefault(); goToSeedStep(); }}
    >
      <div>
        <label class="block text-sm font-medium text-text-secondary" for="handle">
          Handle
        </label>
        <div class="mt-1 flex items-stretch border border-border rounded-md overflow-hidden bg-surface">
          <input
            id="handle"
            type="text"
            bind:value={handle}
            placeholder="tudisco"
            class="flex-1 px-3 py-2 outline-none text-text"
            autocomplete="off"
          />
          {#if serverInfo}
            <span class="px-3 py-2 text-text-muted bg-elevated border-l border-border">
              @{serverInfo.server}
            </span>
          {/if}
        </div>
        <p class="mt-1 text-xs text-text-muted">
          Lowercase letters, digits, <code>-</code>, <code>_</code>. 3–32 chars.
        </p>
      </div>

      <div>
        <label class="block text-sm font-medium text-text-secondary" for="pw">
          Passphrase (encrypts your seed in this browser)
        </label>
        <input
          id="pw"
          type="password"
          bind:value={passphrase}
          class="mt-1 w-full px-3 py-2 border border-border rounded-md outline-none"
          autocomplete="new-password"
        />
        <input
          type="password"
          bind:value={passphrase2}
          placeholder="confirm passphrase"
          class="mt-2 w-full px-3 py-2 border border-border rounded-md outline-none"
          autocomplete="new-password"
        />
        <p class="mt-1 text-xs text-text-muted">
          The seed itself is your real identity. The passphrase only
          protects the local copy in this browser.
        </p>
      </div>

      <button
        type="submit"
        class="px-4 py-2 bg-accent text-accent-contrast rounded-md hover:bg-accent-dim disabled:opacity-50"
        disabled={!serverInfo}
      >
        Continue
      </button>
    </form>
  {/if}

  {#if step === "seed" && id}
    <div class="space-y-4">
      <div class="border border-warning/40 bg-warning/10 rounded-lg p-4 space-y-3">
        <p class="font-semibold text-warning">⚠️ Back up your seed now</p>
        <p class="text-sm text-warning">
          This is the only way to recover your account on another device
          (or after clearing this browser). The server doesn't have it.
          Write it down or paste into a password manager.
        </p>
        <div class="mt-3 p-3 bg-surface border border-warning/40 rounded font-mono text-sm break-all select-all">
          {seedHex}
        </div>
        <div class="flex gap-2">
          <button
            class="text-xs px-3 py-1 bg-warning/10 text-accent-contrast rounded hover:bg-warning/20"
            onclick={() => copyToClipboard(seedHex)}
          >
            Copy seed
          </button>
        </div>
      </div>

      <label class="flex items-start gap-2 text-sm text-text-secondary">
        <input type="checkbox" bind:checked={seedAck} class="mt-1" />
        I've saved this seed somewhere safe. I understand losing it means
        losing my account permanently.
      </label>

      <div class="flex gap-2">
        <button
          class="px-4 py-2 border border-border rounded-md text-text-secondary hover:bg-elevated"
          onclick={() => { step = "handle"; }}
        >
          Back
        </button>
        <button
          class="px-4 py-2 bg-accent text-accent-contrast rounded-md hover:bg-accent-dim disabled:opacity-50"
          disabled={!seedAck}
          onclick={() => { step = "confirm"; }}
        >
          I've saved it — continue
        </button>
      </div>
    </div>
  {/if}

  {#if step === "confirm" && id}
    <div class="space-y-4">
      <p class="text-text-secondary">Ready to register:</p>
      <div class="border border-border rounded-lg p-4 bg-elevated space-y-2 text-sm">
        <div><span class="text-text-muted">Handle:</span> <span class="font-mono font-semibold">{handle}@{serverInfo?.server}</span></div>
        <div><span class="text-text-muted">Public key:</span> <code class="break-all">{id.identity}</code></div>
      </div>

      <div class="flex gap-2">
        <button
          class="px-4 py-2 border border-border rounded-md text-text-secondary hover:bg-elevated"
          onclick={() => { step = "seed"; }}
        >
          Back
        </button>
        <button
          class="px-4 py-2 bg-accent text-accent-contrast rounded-md hover:bg-accent-dim disabled:opacity-50"
          disabled={working}
          onclick={submitRegistration}
        >
          {working ? "Registering…" : "Register"}
        </button>
      </div>
    </div>
  {/if}

  {#if step === "submitting"}
    <p class="text-text-secondary">Submitting registration to {serverInfo?.server}…</p>
  {/if}

  {#if step === "done"}
    <div class="border border-verified/40 bg-verified/10 rounded-lg p-6">
      <p class="text-lg font-semibold text-verified">✓ Account created</p>
      <p class="mt-2 text-sm text-verified">
        You are <span class="font-mono font-semibold">{handle}@{serverInfo?.server}</span>.
      </p>
      <button
        class="mt-4 px-4 py-2 bg-accent text-accent-contrast rounded-md hover:bg-accent-dim"
        onclick={() => push("/welcome")}
      >
        Get started →
      </button>
    </div>
  {/if}
</div>
