<script lang="ts">
  import { onMount } from 'svelte';
  import { Save, TriangleAlert } from 'lucide-svelte';
  import {
    getNetworkSettings,
    updateNetworkSettings,
    type NetworkSettings
  } from '$lib/api/admin';
  import { pushToast } from '$lib/stores/toast.svelte';

  let settings = $state<NetworkSettings | null>(null);
  let hops = $state(1);
  let saving = $state(false);
  let loadError = $state(false);

  const dirty = $derived(!!settings && hops !== settings.trusted_proxy_hops);
  const chain = $derived(
    (settings?.forwarded_chain ?? '')
      .split(',')
      .map((s) => s.trim())
      .filter(Boolean)
  );
  // The operator can count their proxies from what actually arrived rather
  // than guessing — one XFF entry per proxy in front of us.
  const suggested = $derived(chain.length);

  async function load() {
    try {
      settings = await getNetworkSettings();
      hops = settings.trusted_proxy_hops;
      loadError = false;
    } catch {
      loadError = true;
    }
  }

  onMount(load);

  async function save() {
    saving = true;
    try {
      settings = await updateNetworkSettings(hops);
      hops = settings.trusted_proxy_hops;
      pushToast('Proxy depth saved.');
    } catch {
      pushToast("Couldn't save proxy depth.", 'error');
    } finally {
      saving = false;
    }
  }
</script>

<section class="space-y-4 rounded-xl border border-border bg-surface p-5">
  <div>
    <h3 class="font-display text-lg font-medium text-text-primary">Client IP detection</h3>
    <p class="mt-1 text-sm text-text-secondary">
      How many reverse proxies sit in front of Minstrel. This decides which address is
      recorded for each sign-in on the <span class="whitespace-nowrap">Active sessions</span> card,
      so getting it right is what makes an unfamiliar login visible.
    </p>
  </div>

  {#if loadError}
    <p class="text-sm text-action-destructive">
      Couldn't load network settings.
      <button type="button" class="underline hover:no-underline" onclick={load}>Try again</button>
    </p>
  {:else if settings === null}
    <p class="text-sm text-text-secondary">Loading…</p>
  {:else}
    <div class="flex flex-wrap items-end gap-3">
      <label class="flex flex-col gap-1">
        <span class="text-sm text-text-secondary">Trusted proxies</span>
        <input
          type="number"
          min="0"
          max={settings.max_hops}
          bind:value={hops}
          class="w-24 rounded border border-border bg-background px-2 py-1
                 focus-visible:outline focus-visible:outline-2 focus-visible:outline-accent"
        />
      </label>
      <button
        type="button"
        class="inline-flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5
               text-sm hover:bg-surface-hover focus-visible:ring-2 focus-visible:ring-accent
               disabled:opacity-50"
        disabled={saving || !dirty}
        onclick={save}
      >
        <Save size={14} aria-hidden="true" />
        {saving ? 'Saving…' : 'Save'}
      </button>
    </div>

    <!-- Verification, not decoration: the number is abstract, but "the address
         Minstrel currently sees for YOU" is checkable against the machine
         you're sitting at. -->
    <dl class="grid gap-x-4 gap-y-1 text-sm sm:grid-cols-[auto_1fr]">
      <dt class="text-text-secondary">Your address right now</dt>
      <dd class="font-mono">{settings.detected_client_ip || 'unknown'}</dd>
      <dt class="text-text-secondary">Direct connection from</dt>
      <dd class="font-mono">{settings.remote_addr || 'unknown'}</dd>
      <dt class="text-text-secondary">Forwarded chain</dt>
      <dd class="font-mono break-all">{settings.forwarded_chain || '(none)'}</dd>
    </dl>

    {#if suggested > 0 && settings.trusted_proxy_hops !== suggested}
      <p class="text-sm text-text-secondary">
        This request arrived with {suggested}
        {suggested === 1 ? 'forwarded address' : 'forwarded addresses'}, which usually means
        {suggested}
        {suggested === 1 ? 'proxy' : 'proxies'} in front of Minstrel.
      </p>
    {/if}

    <div class="space-y-2 rounded border border-border bg-background p-3 text-sm">
      <p class="flex items-start gap-2 text-text-secondary">
        <TriangleAlert size={14} class="mt-0.5 flex-shrink-0 text-action-destructive" aria-hidden="true" />
        <span>
          Count your proxies — don't guess high. This number tells Minstrel how much of the
          <span class="font-mono">X-Forwarded-For</span> header to believe, and that header is
          written by whoever connects. Set it higher than your real chain, or above 0 with no
          proxy at all, and a visitor can choose which address their own session shows — which
          defeats the point of the sessions list.
        </span>
      </p>
      <ul class="ml-6 list-disc space-y-1 text-text-secondary">
        <li><strong>0</strong> — no proxy; Minstrel is reached directly.</li>
        <li><strong>1</strong> — one reverse proxy, e.g. nginx, Caddy or Traefik terminating TLS.</li>
        <li><strong>2</strong> — a CDN in front of your own proxy, e.g. Cloudflare → nginx.</li>
      </ul>
    </div>
  {/if}
</section>
