<script lang="ts">
  import { pageTitle } from '$lib/branding';
  import { Save, RefreshCw, Trash2 } from 'lucide-svelte';
  import { useQueryClient } from '@tanstack/svelte-query';
  import {
    createLidarrConfigQuery,
    createQualityProfilesQuery,
    createMetadataProfilesQuery,
    createRootFoldersQuery,
    putLidarrConfig,
    testLidarrConnection
  } from '$lib/api/admin';
  import { qk } from '$lib/api/queries';
  import type { LidarrConfig, LidarrTestResult } from '$lib/api/types';

  // Lidarr connection panel. The "saved api key" is masked as "***" on GET —
  // never displayed in the input. The input always starts empty; sending an
  // empty string on PUT tells the backend "preserve the saved key". This is
  // the one field with that semantics; everything else is sent as-typed.

  const client = useQueryClient();

  const configStore = createLidarrConfigQuery();
  const config = $derived($configStore);

  // Local form state — initialized once when config first loads. Subsequent
  // refetches don't clobber whatever the operator is in the middle of editing.
  let baseUrl = $state('');
  let apiKeyInput = $state(''); // intentionally never seeded with '***'
  let qualityId = $state<number>(0);
  let metadataId = $state<number>(0);
  let rootPath = $state<string>('');
  let initialized = false;

  $effect(() => {
    const c = config.data;
    if (c && !initialized) {
      baseUrl = c.base_url;
      qualityId = c.default_quality_profile_id;
      metadataId = c.default_metadata_profile_id;
      rootPath = c.default_root_folder_path;
      initialized = true;
    }
  });

  // Auto-default to the first option Lidarr returns when the operator
  // hasn't picked one yet. Saves a click for the common case (one
  // profile + one root folder, which is what most home setups have).
  // The operator can still change any of them before saving.
  $effect(() => {
    if (qualityId === 0 && profiles.data && profiles.data.length > 0) {
      qualityId = profiles.data[0].id;
    }
  });
  $effect(() => {
    if (metadataId === 0 && metadataProfiles.data && metadataProfiles.data.length > 0) {
      metadataId = metadataProfiles.data[0].id;
    }
  });
  $effect(() => {
    if (rootPath === '' && folders.data && folders.data.length > 0) {
      rootPath = folders.data[0].path;
    }
  });

  // The dropdown queries only fire once Lidarr is configured; otherwise the
  // backend has no client to call and would 4xx.
  const profilesEnabled = $derived(!!config.data?.enabled);

  const profilesStore = $derived(createQualityProfilesQuery(profilesEnabled));
  const profiles = $derived($profilesStore);

  const metadataProfilesStore = $derived(createMetadataProfilesQuery(profilesEnabled));
  const metadataProfiles = $derived($metadataProfilesStore);

  const foldersStore = $derived(createRootFoldersQuery(profilesEnabled));
  const folders = $derived($foldersStore);

  let testResult: LidarrTestResult | null = $state(null);
  let saveError: string | null = $state(null);
  let isSaving = $state(false);
  let isTesting = $state(false);

  async function onSave() {
    isSaving = true;
    saveError = null;
    try {
      const cfg: LidarrConfig = {
        enabled: true,
        base_url: baseUrl,
        api_key: apiKeyInput, // empty string tells backend "preserve saved key"
        default_quality_profile_id: qualityId,
        default_metadata_profile_id: metadataId,
        default_root_folder_path: rootPath
      };
      await putLidarrConfig(cfg);
      // Invalidate config + profile/folder lists. A new base_url means a
      // different server, so the cached lists must refetch.
      await Promise.all([
        client.invalidateQueries({ queryKey: qk.lidarrConfig() }),
        client.invalidateQueries({ queryKey: qk.lidarrQualityProfiles() }),
        client.invalidateQueries({ queryKey: qk.lidarrMetadataProfiles() }),
        client.invalidateQueries({ queryKey: qk.lidarrRootFolders() })
      ]);
      apiKeyInput = '';
    } catch (e) {
      saveError = (e as { code?: string }).code ?? 'save_failed';
    } finally {
      isSaving = false;
    }
  }

  async function onTest() {
    isTesting = true;
    testResult = null;
    try {
      testResult = await testLidarrConnection({
        base_url: baseUrl,
        api_key: apiKeyInput
      });
    } finally {
      isTesting = false;
    }
  }

  // Disconnect typed-confirm modal. Requires the literal "DISCONNECT" string
  // (whitespace-trimmed) to avoid muscle-memory clearing of an integration the
  // operator depends on.
  let modalOpen = $state(false);
  let disconnectInput = $state('');
  let disconnectError = $state<string | null>(null);
  const canDisconnect = $derived(disconnectInput.trim() === 'DISCONNECT');

  async function onConfirmDisconnect() {
    if (!canDisconnect) return;
    disconnectError = null;
    try {
      await putLidarrConfig({
        enabled: false,
        base_url: '',
        api_key: '',
        default_quality_profile_id: 0,
        default_metadata_profile_id: 0,
        default_root_folder_path: ''
      });
      await Promise.all([
        client.invalidateQueries({ queryKey: qk.lidarrConfig() }),
        client.invalidateQueries({ queryKey: qk.lidarrQualityProfiles() }),
        client.invalidateQueries({ queryKey: qk.lidarrMetadataProfiles() }),
        client.invalidateQueries({ queryKey: qk.lidarrRootFolders() })
      ]);
      modalOpen = false;
      disconnectInput = '';
    } catch (e) {
      disconnectError = (e as { code?: string }).code ?? 'disconnect_failed';
    }
  }

  function cancelDisconnect() {
    modalOpen = false;
    disconnectInput = '';
    disconnectError = null;
  }
</script>

<svelte:head><title>{pageTitle('Admin · Integrations')}</title></svelte:head>

<div class="space-y-6">
  <header class="flex items-center justify-between">
    <h2 class="font-display text-2xl font-medium text-text-primary">Integrations</h2>
    {#if config.data?.enabled}
      <span
        class="inline-flex items-center gap-2 rounded-md bg-accent-tint px-3 py-1 text-xs font-medium text-action-primary"
      >
        <span class="h-1.5 w-1.5 rounded-full bg-action-primary"></span>
        Lidarr · connected
      </span>
    {:else}
      <span
        class="inline-flex items-center gap-2 rounded-md border border-border px-3 py-1 text-xs text-text-muted"
      >
        <span class="h-1.5 w-1.5 rounded-full bg-text-muted"></span>
        Lidarr · unset
      </span>
    {/if}
  </header>

  <!-- Lidarr panel -->
  <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">Lidarr</h3>
      <p class="mt-1 text-sm text-text-secondary">
        Search Lidarr from <span class="font-mono text-accent">/discover</span> and
        route approved requests to it.
      </p>
    </div>

    <label class="block">
      <span class="block text-sm text-text-secondary">Base URL</span>
      <input
        type="text"
        bind:value={baseUrl}
        placeholder="http://lidarr.lan:8686"
        class="mt-1 w-full rounded-md border border-border bg-background px-3 py-2 font-mono text-sm text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-accent"
      />
    </label>

    <label class="block">
      <span class="block text-sm text-text-secondary">API key</span>
      <input
        type="password"
        bind:value={apiKeyInput}
        placeholder={config.data?.api_key === '***'
          ? '••• (saved — leave empty to keep)'
          : 'Paste API key'}
        class="mt-1 w-full rounded-md border border-border bg-background px-3 py-2 font-mono text-sm text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-accent"
      />
    </label>

    <label class="block">
      <span class="block text-sm text-text-secondary">Default quality profile</span>
      <select
        bind:value={qualityId}
        disabled={!profilesEnabled || profiles.isPending}
        class="mt-1 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-accent disabled:opacity-50"
      >
        {#each profiles.data ?? [] as p (p.id)}
          <option value={p.id}>{p.name}</option>
        {/each}
      </select>
    </label>

    <label class="block">
      <span class="block text-sm text-text-secondary">Default metadata profile</span>
      <select
        bind:value={metadataId}
        disabled={!profilesEnabled || metadataProfiles.isPending}
        class="mt-1 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-accent disabled:opacity-50"
      >
        {#each metadataProfiles.data ?? [] as p (p.id)}
          <option value={p.id}>{p.name}</option>
        {/each}
      </select>
    </label>

    <label class="block">
      <span class="block text-sm text-text-secondary">Default root folder</span>
      <select
        bind:value={rootPath}
        disabled={!profilesEnabled || folders.isPending}
        class="mt-1 w-full rounded-md border border-border bg-background px-3 py-2 font-mono text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-accent disabled:opacity-50"
      >
        {#each folders.data ?? [] as f (f.path)}
          <option value={f.path}
            >{f.path}{f.accessible ? '' : ' (not accessible)'}</option
          >
        {/each}
      </select>
    </label>

    {#if testResult}
      {#if testResult.ok}
        <p class="text-sm text-action-primary">
          Connected — Lidarr {testResult.version}
        </p>
      {:else}
        <p class="text-sm text-error">Connection failed — {testResult.error}</p>
      {/if}
    {/if}
    {#if saveError}
      <p class="text-sm text-error">Save failed — {saveError}</p>
    {/if}

    <div class="flex items-center gap-2 pt-2">
      <button
        type="button"
        onclick={onSave}
        disabled={isSaving}
        class="inline-flex items-center gap-2 rounded-md bg-action-primary px-3 py-1.5 text-sm text-action-fg disabled:opacity-50"
      >
        <Save size={14} strokeWidth={2} />
        Save changes
      </button>
      <button
        type="button"
        onclick={onTest}
        disabled={isTesting}
        class="inline-flex items-center gap-2 rounded-md border border-border bg-transparent px-3 py-1.5 text-sm text-text-secondary hover:text-text-primary disabled:opacity-50"
      >
        <RefreshCw size={14} strokeWidth={2} />
        Test connection
      </button>
      <button
        type="button"
        onclick={() => (modalOpen = true)}
        class="ml-auto inline-flex items-center gap-2 rounded-md bg-action-destructive px-3 py-1.5 text-sm text-action-fg"
      >
        <Trash2 size={14} strokeWidth={2} />
        Disconnect
      </button>
    </div>
  </section>

  <!-- MusicBrainz overrides — visually present, not implemented. Foreshadows
       future integrations so the page doesn't read like Lidarr-only. -->
  <section class="space-y-2 rounded-xl border border-border bg-surface p-5 opacity-60">
    <div class="flex items-center justify-between">
      <h3 class="font-display text-lg font-medium text-text-primary">
        MusicBrainz overrides
      </h3>
      <span
        class="inline-flex items-center gap-2 rounded-md border border-border px-3 py-1 text-xs text-text-muted"
      >
        <span class="h-1.5 w-1.5 rounded-full bg-text-muted"></span>
        unset
      </span>
    </div>
    <p class="text-sm text-text-secondary">Not yet configured.</p>
  </section>
</div>

{#if modalOpen}
  <!-- svelte-ignore a11y_click_events_have_key_events -->
  <!-- svelte-ignore a11y_no_static_element_interactions -->
  <div
    class="fixed inset-0 z-50 flex items-center justify-center"
    style="background: rgba(0,0,0,0.5);"
    onclick={cancelDisconnect}
  >
    <div
      role="dialog"
      aria-modal="true"
      aria-labelledby="disconnect-title"
      class="w-full max-w-md rounded-xl border border-border bg-surface p-5 shadow-lg"
      onclick={(e) => e.stopPropagation()}
      tabindex="-1"
    >
      <h3
        id="disconnect-title"
        class="font-display text-lg font-medium text-text-primary"
      >
        Disconnect Lidarr?
      </h3>
      <p class="mt-2 text-text-secondary">
        This clears the saved configuration. Type
        <span class="font-mono text-text-primary">DISCONNECT</span> to remove the
        Lidarr connection.
      </p>
      <input
        type="text"
        bind:value={disconnectInput}
        placeholder="DISCONNECT"
        aria-label="Type DISCONNECT to confirm"
        class="mt-3 w-full rounded-md border border-border bg-background px-3 py-2 font-mono text-sm text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-accent"
      />
      {#if disconnectError}
        <p class="mt-2 text-sm text-error">Disconnect failed — {disconnectError}</p>
      {/if}
      <div class="mt-5 flex justify-end gap-2">
        <button
          type="button"
          onclick={cancelDisconnect}
          class="rounded-md bg-action-secondary px-3 py-1.5 text-sm text-action-fg"
        >
          Cancel
        </button>
        <button
          type="button"
          onclick={onConfirmDisconnect}
          disabled={!canDisconnect}
          class="rounded-md bg-action-destructive px-3 py-1.5 text-sm text-action-fg disabled:opacity-50"
        >
          Disconnect
        </button>
      </div>
    </div>
  </div>
{/if}
