<script>
  import { onMount } from "svelte";

  let termEl;
  let connected = $state(false);
  let error = $state("");

  onMount(async () => {
    try {
      const { Terminal } = await import("@xterm/xterm");
      const { FitAddon } = await import("@xterm/addon-fit");
      await import("@xterm/xterm/css/xterm.css");

      const term = new Terminal({
        cursorBlink: true,
        fontSize: 13,
        fontFamily: "'JetBrains Mono', 'Fira Code', 'SF Mono', 'Menlo', monospace",
        lineHeight: 1.4,
        theme: {
          background: "#0f172a",
          foreground: "#e2e8f0",
          cursor: "#6366f1",
          cursorAccent: "#0f172a",
          selectionBackground: "#334155",
          black: "#0f172a",
          red: "#f43f5e",
          green: "#10b981",
          yellow: "#f59e0b",
          blue: "#3b82f6",
          magenta: "#a855f7",
          cyan: "#06b6d4",
          white: "#e2e8f0",
        },
      });
      const fit = new FitAddon();
      term.loadAddon(fit);
      term.open(termEl);
      fit.fit();

      const proto = location.protocol === "https:" ? "wss:" : "ws:";
      const token = localStorage.getItem("token") || "";
      const ws = new WebSocket(`${proto}//${location.host}/ws/terminal?token=${encodeURIComponent(token)}`);
      ws.binaryType = "arraybuffer";

      ws.onopen = () => {
        connected = true;
        const buf = new Uint8Array(5);
        buf[0] = 0x01;
        new DataView(buf.buffer).setUint16(1, term.cols);
        new DataView(buf.buffer).setUint16(3, term.rows);
        ws.send(buf);
      };
      ws.onmessage = (e) => term.write(new Uint8Array(e.data));
      ws.onclose = () => {
        connected = false;
        term.write("\r\n\x1b[90m[Connection closed]\x1b[0m");
      };
      ws.onerror = () => {
        error = "WebSocket connection failed. Terminal requires Tailscale access.";
      };
      term.onData((data) => ws.readyState === 1 && ws.send(new TextEncoder().encode(data)));

      const ro = new ResizeObserver(() => {
        fit.fit();
        if (ws.readyState === 1) {
          const buf = new Uint8Array(5);
          buf[0] = 0x01;
          new DataView(buf.buffer).setUint16(1, term.cols);
          new DataView(buf.buffer).setUint16(3, term.rows);
          ws.send(buf);
        }
      });
      ro.observe(termEl);
    } catch (e) {
      error = "Failed to initialize terminal: " + e.message;
    }
  });
</script>

<div class="space-y-4">
  <div class="flex items-center justify-between">
    <div>
      <h1 class="text-2xl font-bold text-surface-900 tracking-tight">Terminal</h1>
      <p class="text-sm text-surface-400 mt-1">
        {#if connected}
          <span class="inline-flex items-center gap-1.5">
            <span class="w-1.5 h-1.5 rounded-full bg-emerald-500"></span>
            Connected
          </span>
        {:else if error}
          <span class="text-rose-500">{error}</span>
        {:else}
          <span class="inline-flex items-center gap-1.5">
            <span class="w-1.5 h-1.5 rounded-full bg-amber-400 animate-pulse"></span>
            Connecting...
          </span>
        {/if}
      </p>
    </div>
  </div>

  <div
    bind:this={termEl}
    class="h-[calc(100vh-10rem)] rounded-xl overflow-hidden shadow-lg border border-surface-700"
    style="background: #0f172a;"
  ></div>
</div>
