<script lang="ts">
  import { onMount, onDestroy } from 'svelte';
  import { appRpc } from '../rpc.ts';
  import {
    getMachines, addMachine, removeMachine, updateMachineStatus,
    type RemoteMachine, type MachineStatus,
  } from '../machines-store.svelte.ts';

  // ── Form state ───────────────────────────────────────────────────────────

  let newUrl   = $state('');
  let newToken = $state('');
  let newLabel = $state('');
  let error    = $state<string | null>(null);
  let loading  = $state(false);

  // ── Derived machine list ────────────────────────────────────────────────

  let machines = $derived(getMachines());

  // ── Poll for machine list from Bun ──────────────────────────────────────

  let pollTimer: ReturnType<typeof setInterval> | null = null;

  async function refreshMachines() {
    if (!appRpc) return;
    try {
      const { machines: list } = await appRpc.request['remote.list']({});
      for (const m of list) {
        const existing = getMachines().find(x => x.machineId === m.machineId);
        if (!existing) {
          addMachine(m.machineId, m.url, m.label);
        }
        updateMachineStatus(m.machineId, m.status as MachineStatus);
      }
    } catch { /* best-effort */ }
  }

  onMount(() => {
    refreshMachines();
    pollTimer = setInterval(refreshMachines, 5_000);
  });

  onDestroy(() => {
    if (pollTimer) clearInterval(pollTimer);
  });

  // ── Actions ──────────────────────────────────────────────────────────────

  async function handleConnect() {
    if (!newUrl.trim() || !newToken.trim()) {
      error = 'URL and token are required.';
      return;
    }
    error = null;
    loading = true;

    try {
      const res = await appRpc.request['remote.connect']({
        url: newUrl.trim(),
        token: newToken.trim(),
        label: newLabel.trim() || undefined,
      });

      if (res.ok && res.machineId) {
        addMachine(res.machineId, newUrl.trim(), newLabel.trim() || undefined);
        newUrl = '';
        newToken = '';
        newLabel = '';
      } else {
        error = res.error ?? 'Connection failed';
      }
    } catch (err) {
      error = err instanceof Error ? err.message : 'Connection failed';
    } finally {
      loading = false;
    }
  }

  async function handleDisconnect(machineId: string) {
    try {
      await appRpc.request['remote.disconnect']({ machineId });
      updateMachineStatus(machineId, 'disconnected');
    } catch { /* ignore */ }
  }

  // Fix #6 (Codex audit): Use remote.remove RPC that disconnects AND deletes
  async function handleRemove(machineId: string) {
    try {
      await appRpc.request['remote.remove']({ machineId });
    } catch { /* may already be disconnected/removed */ }
    removeMachine(machineId);
  }

  function statusColor(status: MachineStatus): string {
    switch (status) {
      case 'connected':    return 'var(--ctp-green)';
      case 'connecting':   return 'var(--ctp-yellow)';
      case 'error':        return 'var(--ctp-red)';
      case 'disconnected': return 'var(--ctp-overlay0)';
    }
  }

  function statusLabel(status: MachineStatus): string {
    return status.charAt(0).toUpperCase() + status.slice(1);
  }

  function formatLatency(ms: number | null): string {
    if (ms === null) return '--';
    return `${ms}ms`;
  }
</script>

<div class="section">
  <h3 class="sh">Connected Machines</h3>

  {#if machines.length === 0}
    <p class="empty">No remote machines configured.</p>
  {:else}
    <div class="machine-list">
      {#each machines as m (m.machineId)}
        <div class="machine-row">
          <div class="machine-info">
            <span class="status-dot" style:background={statusColor(m.status)}></span>
            <div class="machine-detail">
              <span class="machine-label">{m.label}</span>
              <span class="machine-url">{m.url}</span>
            </div>
          </div>
          <div class="machine-meta">
            <span class="latency">{formatLatency(m.latencyMs)}</span>
            <span class="status-text" style:color={statusColor(m.status)}>
              {statusLabel(m.status)}
            </span>
            {#if m.error}
              <span class="machine-error" title={m.error}>{m.error}</span>
            {/if}
          </div>
          <div class="machine-actions">
            {#if m.status === 'connected'}
              <button class="action-btn danger" onclick={() => handleDisconnect(m.machineId)}>
                Disconnect
              </button>
            {:else if m.status === 'disconnected' || m.status === 'error'}
              <button class="action-btn" onclick={() => {
                appRpc.request['remote.connect']({
                  url: m.url, token: '', label: m.label,
                }).catch(() => {});
              }}>Reconnect</button>
            {/if}
            <button class="action-btn secondary" onclick={() => handleRemove(m.machineId)}
              title="Remove machine">
              x
            </button>
          </div>
        </div>
      {/each}
    </div>
  {/if}

  <h3 class="sh" style="margin-top: 1rem;">Add Machine</h3>

  <div class="field">
    <label class="lbl" for="rm-label">Label (optional)</label>
    <input id="rm-label" class="text-in" bind:value={newLabel}
      placeholder="e.g. build-server" />
  </div>

  <div class="field">
    <label class="lbl" for="rm-url">Relay URL</label>
    <input id="rm-url" class="text-in" bind:value={newUrl}
      placeholder="wss://relay.example.com:9750" />
  </div>

  <div class="field">
    <label class="lbl" for="rm-token">Auth token</label>
    <input id="rm-token" class="text-in" type="password" bind:value={newToken}
      placeholder="Bearer token" />
  </div>

  {#if error}
    <p class="error-msg">{error}</p>
  {/if}

  <button class="connect-btn" onclick={handleConnect} disabled={loading}>
    {loading ? 'Connecting...' : 'Connect'}
  </button>
</div>

<style>
  .section { display: flex; flex-direction: column; gap: 0.5rem; }
  .sh { margin: 0.125rem 0; font-size: 0.6875rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ctp-overlay0); }
  .lbl { font-size: 0.75rem; color: var(--ctp-subtext0); }
  .field { display: flex; flex-direction: column; gap: 0.2rem; }
  .empty { font-size: 0.8rem; color: var(--ctp-overlay0); margin: 0; font-style: italic; }

  .text-in {
    padding: 0.3rem 0.5rem; background: var(--ctp-surface0);
    border: 1px solid var(--ctp-surface1); border-radius: 0.25rem;
    color: var(--ctp-text); font-size: 0.8125rem;
    font-family: var(--ui-font-family);
  }
  .text-in:focus { outline: none; border-color: var(--ctp-blue); }

  .machine-list { display: flex; flex-direction: column; gap: 0.25rem; }

  .machine-row {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.375rem 0.5rem; background: var(--ctp-surface0);
    border: 1px solid var(--ctp-surface1); border-radius: 0.25rem;
  }

  .machine-info { display: flex; align-items: center; gap: 0.5rem; flex: 1; min-width: 0; }

  .status-dot {
    width: 8px; height: 8px; border-radius: 50%;
    flex-shrink: 0;
  }

  .machine-detail {
    display: flex; flex-direction: column; min-width: 0;
  }

  .machine-label {
    font-size: 0.8rem; color: var(--ctp-text); font-weight: 500;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }

  .machine-url {
    font-size: 0.6875rem; color: var(--ctp-overlay0);
    font-family: var(--term-font-family, monospace);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }

  .machine-meta {
    display: flex; flex-direction: column; align-items: flex-end;
    gap: 0.125rem; flex-shrink: 0;
  }

  .latency {
    font-size: 0.6875rem; color: var(--ctp-overlay1);
    font-family: var(--term-font-family, monospace);
  }

  .status-text { font-size: 0.6875rem; font-weight: 500; }
  .machine-error { font-size: 0.625rem; color: var(--ctp-red); max-width: 10rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  .machine-actions { display: flex; gap: 0.25rem; flex-shrink: 0; }

  .action-btn {
    padding: 0.2rem 0.5rem; background: var(--ctp-surface0);
    border: 1px solid var(--ctp-surface1); border-radius: 0.25rem;
    color: var(--ctp-subtext1); font-size: 0.7rem; cursor: pointer;
    font-family: var(--ui-font-family);
    transition: background 0.12s, color 0.12s;
  }
  .action-btn:hover { background: var(--ctp-surface1); color: var(--ctp-text); }
  .action-btn.secondary { color: var(--ctp-overlay0); }
  .action-btn.danger { color: var(--ctp-red); border-color: color-mix(in srgb, var(--ctp-red) 30%, var(--ctp-surface1)); }
  .action-btn.danger:hover { background: color-mix(in srgb, var(--ctp-red) 15%, var(--ctp-surface0)); }

  .error-msg { font-size: 0.75rem; color: var(--ctp-red); margin: 0; }

  .connect-btn {
    align-self: flex-start;
    padding: 0.3rem 1rem; background: var(--ctp-blue);
    border: none; border-radius: 0.25rem;
    color: var(--ctp-base); font-size: 0.8rem; font-weight: 600;
    cursor: pointer; font-family: var(--ui-font-family);
    transition: opacity 0.12s;
  }
  .connect-btn:hover:not(:disabled) { opacity: 0.85; }
  .connect-btn:disabled { opacity: 0.4; cursor: not-allowed; }
</style>
