<script>
  import { login, setToken } from "../lib/api.js";
  import { fade, fly } from "svelte/transition";

  let username = $state("");
  let password = $state("");
  let totp_code = $state("");
  let error = $state("");
  let loading = $state(false);
  let require2FA = $state(false);
  let showPasswordForm = $state(!window.isSecureContext);

  function base64urlToBuffer(b64) {
    const s = b64.replace(/-/g, '+').replace(/_/g, '/');
    const raw = atob(s);
    return Uint8Array.from(raw, c => c.charCodeAt(0)).buffer;
  }

  function bufferToBase64url(buf) {
    const bytes = new Uint8Array(buf);
    let s = '';
    bytes.forEach(b => s += String.fromCharCode(b));
    return btoa(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
  }

  async function loginWithPasskey() {
    loading = true;
    error = "";
    try {
      const r = await fetch("/api/auth/passkey/login/options", { method: "POST" });
      if (!r.ok) throw new Error("No passkeys registered");
      const opts = await r.json();
      opts.challenge = base64urlToBuffer(opts.challenge);
      if (opts.allowCredentials) {
        opts.allowCredentials = opts.allowCredentials.map(c => ({
          ...c, id: base64urlToBuffer(c.id)
        }));
      }
      const cred = await navigator.credentials.get({ publicKey: opts });
      const body = {
        id: cred.id,
        rawId: bufferToBase64url(cred.rawId),
        type: cred.type,
        response: {
          authenticatorData: bufferToBase64url(cred.response.authenticatorData),
          clientDataJSON: bufferToBase64url(cred.response.clientDataJSON),
          signature: bufferToBase64url(cred.response.signature),
          userHandle: cred.response.userHandle ? bufferToBase64url(cred.response.userHandle) : null,
        },
      };
      const res = await fetch("/api/auth/passkey/login/verify", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      });
      if (!res.ok) { const e = await res.json(); throw new Error(e.detail || "Passkey verification failed"); }
      const data = await res.json();
      setToken(data.access_token);
      window.location.reload();
    } catch (e) {
      if (e.name === "NotAllowedError") { error = "Passkey authentication cancelled"; }
      else { error = e.message || "Passkey login failed"; }
      showPasswordForm = true;
    } finally {
      loading = false;
    }
  }

  async function handleSubmit(e) {
    e.preventDefault();
    loading = true;
    error = "";
    
    try {
      const payload = { username, password };
      if (require2FA) payload.totp_code = totp_code;
      
      const res = await login(payload); // api.js helper sends JSON
      
      setToken(res.access_token);
      // Determine if we need to reload or just update state. 
      // Reload is safest to clear any stale state.
      window.location.reload(); 
      
    } catch (e) {
      if (e.status === 403 && e.body?.detail === "2FA code required") {
         require2FA = true;
         // Clear error if any
         error = "";
      } else {
         error = e.body?.detail || "Login failed. Please check your credentials.";
         // Reset 2FA state on general failure (maybe password was wrong this time)
         if (!require2FA) {
            password = "";
         }
      }
    } finally {
      loading = false;
    }
  }
</script>

<div class="flex min-h-screen items-center justify-center bg-surface-50 dark:bg-surface-950 px-4">
  <div class="w-full max-w-sm space-y-8 bg-white dark:bg-surface-900 p-8 rounded-2xl shadow-xl border border-surface-200 dark:border-surface-800" in:fly={{ y: 20, duration: 400 }}>
    <div class="text-center">
      <div class="mx-auto h-12 w-12 bg-gradient-to-br from-primary-500 to-primary-600 rounded-xl flex items-center justify-center shadow-lg mb-4">
        <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
        </svg>
      </div>
      <h2 class="text-2xl font-bold tracking-tight text-surface-900 dark:text-white">Sign in to NAS</h2>
      <p class="mt-2 text-sm text-surface-600 dark:text-surface-400">
        Enter your credentials to access the dashboard
      </p>
    </div>

    <div class="mt-8 space-y-6">
      {#if !showPasswordForm && !require2FA}
        <button
          type="button"
          disabled={loading}
          onclick={loginWithPasskey}
          class="flex w-full justify-center rounded-lg bg-surface-800 dark:bg-surface-700 px-3 py-2.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-surface-700 dark:hover:bg-surface-600 disabled:opacity-70 transition-all active:scale-[0.98]"
        >
          {#if loading}
            <svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" fill="none" viewBox="0 0 24 24">
              <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
              <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
            </svg>
          {/if}
          Sign in with Passkey
        </button>

        <div class="relative">
          <div class="absolute inset-0 flex items-center"><div class="w-full border-t border-surface-200 dark:border-surface-700"></div></div>
          <div class="relative flex justify-center text-xs"><span class="bg-white dark:bg-surface-900 px-2 text-surface-400">or</span></div>
        </div>

        <button type="button" onclick={() => showPasswordForm = true} class="flex w-full justify-center text-sm text-primary-500 hover:text-primary-400">
          Use password instead
        </button>
      {/if}

      {#if showPasswordForm || require2FA}
      <form class="space-y-6" onsubmit={handleSubmit}>
      <div class="space-y-4">
        {#if !require2FA}
          <div>
            <label for="username" class="sr-only">Username</label>
            <input
              id="username"
              name="username"
              type="text"
              required
              bind:value={username}
              class="relative block w-full rounded-lg border-0 py-2.5 px-3 text-surface-900 dark:text-white ring-1 ring-inset ring-surface-300 dark:ring-surface-700 placeholder:text-surface-400 focus:z-10 focus:ring-2 focus:ring-inset focus:ring-primary-600 dark:bg-surface-800 sm:text-sm sm:leading-6"
              placeholder="Username"
            />
          </div>
          <div>
            <label for="password" class="sr-only">Password</label>
            <input
              id="password"
              name="password"
              type="password"
              required
              bind:value={password}
              class="relative block w-full rounded-lg border-0 py-2.5 px-3 text-surface-900 dark:text-white ring-1 ring-inset ring-surface-300 dark:ring-surface-700 placeholder:text-surface-400 focus:z-10 focus:ring-2 focus:ring-inset focus:ring-primary-600 dark:bg-surface-800 sm:text-sm sm:leading-6"
              placeholder="Password"
            />
          </div>
        {:else}
          <div in:fade>
            <label for="totp" class="block text-sm font-medium leading-6 text-surface-900 dark:text-white text-center mb-2">Authenticator Code</label>
            <input
              id="totp"
              name="totp"
              type="text"
              inputmode="numeric"
              pattern="[0-9]*"
              autocomplete="one-time-code"
              required
              autofocus
              bind:value={totp_code}
              class="block w-full text-center tracking-[0.5em] text-2xl font-mono rounded-lg border-0 py-3 text-surface-900 dark:text-white ring-1 ring-inset ring-surface-300 dark:ring-surface-700 placeholder:text-surface-400 focus:ring-2 focus:ring-inset focus:ring-primary-600 dark:bg-surface-800"
              placeholder="000000"
              maxlength="6"
            />
            <p class="mt-4 text-center text-sm text-surface-500">
              <button type="button" class="text-primary-500 hover:text-primary-400" onclick={() => require2FA = false}>
                Back to credentials
              </button>
            </p>
          </div>
        {/if}
      </div>

        <button
          type="submit"
          disabled={loading}
          class="flex w-full justify-center rounded-lg bg-primary-600 px-3 py-2.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 disabled:opacity-70 transition-all active:scale-[0.98]"
        >
          {#if loading}
            <svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" fill="none" viewBox="0 0 24 24">
              <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
              <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
            </svg>
          {/if}
          {require2FA ? "Verify Code" : "Sign in"}
        </button>
      </form>
      {/if}

      {#if error}
        <div class="rounded-md bg-red-50 dark:bg-red-900/30 p-3" in:fade>
          <div class="flex">
            <div class="flex-shrink-0">
              <svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
                <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
              </svg>
            </div>
            <div class="ml-3">
              <h3 class="text-sm font-medium text-red-800 dark:text-red-200">{error}</h3>
            </div>
          </div>
        </div>
      {/if}
    </div>
  </div>
</div>
