<script lang="ts">
  import { onMount } from 'svelte'
  import { fetchSignals, ackSignal, resolveSignal, muteSignal, type Signal } from '$lib/api'
  import { liveEvents, subscribeEvents } from '$lib/stores/events'
  import * as Tabs from '$lib/components/ui/tabs'
  import * as Table from '$lib/components/ui/table'
  import { Badge } from '$lib/components/ui/badge'
  import { Button } from '$lib/components/ui/button'
  import * as Select from '$lib/components/ui/select'
  import { toast } from 'svelte-sonner'

  let signals = $state<Signal[]>([])
  let severityFilter = $state('all')
  let acting = $state<string | null>(null)

  async function load() {
    signals = await fetchSignals()
  }

  onMount(() => {
    load()
    const unsubscribe = subscribeEvents()
    return unsubscribe
  })

  $effect(() => {
    const ev = $liveEvents[0]
    if (!ev || !ev.type.startsWith('signal.')) return
    load()
  })

  async function ack(id: string) {
    acting = id
    const result = await ackSignal(id)
    acting = null
    if (result) {
      toast.success('Signal acknowledged')
      load()
    } else {
      toast.error('Acknowledge failed')
    }
  }

  async function resolve(id: string) {
    acting = id
    const result = await resolveSignal(id)
    acting = null
    if (result) {
      toast.success('Signal resolved')
      load()
    } else {
      toast.error('Resolve failed')
    }
  }

  async function mute(id: string) {
    acting = id
    const muteUntil = new Date(Date.now() + 60 * 60 * 1000).toISOString()
    const result = await muteSignal(id, muteUntil)
    acting = null
    if (result) {
      toast.success('Signal muted for 1h')
      load()
    } else {
      toast.error('Mute failed')
    }
  }

  function severityVariant(sev: string): 'default' | 'secondary' | 'destructive' {
    if (sev === 'critical') return 'destructive'
    if (sev === 'warning') return 'secondary'
    return 'default'
  }

  function bySeverity(list: Signal[]) {
    return severityFilter === 'all' ? list : list.filter((s) => s.severity === severityFilter)
  }

  const open = $derived(bySeverity(signals.filter((s) => ['raised', 'acknowledged', 'acting'].includes(s.state))))
  const muted = $derived(bySeverity(signals.filter((s) => s.state === 'muted')))
  const resolved = $derived(bySeverity(signals.filter((s) => ['resolved', 'failed'].includes(s.state))))
</script>

{#snippet signalTable(list: Signal[], showActions: boolean)}
  <div class="rounded-md border">
    <Table.Root>
      <Table.Header>
        <Table.Row>
          <Table.Head>Target</Table.Head>
          <Table.Head>Kind</Table.Head>
          <Table.Head>Severity</Table.Head>
          <Table.Head>State</Table.Head>
          <Table.Head>Occurrences</Table.Head>
          <Table.Head>Last seen</Table.Head>
          {#if showActions}
            <Table.Head class="text-right">Actions</Table.Head>
          {/if}
        </Table.Row>
      </Table.Header>
      <Table.Body>
        {#each list as signal (signal.id)}
          <Table.Row>
            <Table.Cell class="font-mono text-xs">{signal.target ?? '—'}</Table.Cell>
            <Table.Cell>{signal.kind}</Table.Cell>
            <Table.Cell><Badge variant={severityVariant(signal.severity)}>{signal.severity}</Badge></Table.Cell>
            <Table.Cell><Badge variant="outline">{signal.state}</Badge></Table.Cell>
            <Table.Cell>{signal.occurrence_count}</Table.Cell>
            <Table.Cell class="text-xs text-muted-foreground"
              >{new Date(signal.last_seen_at).toLocaleString()}</Table.Cell
            >
            {#if showActions}
              <Table.Cell class="flex justify-end gap-2">
                {#if signal.state === 'raised'}
                  <Button size="sm" variant="outline" disabled={acting === signal.id} onclick={() => ack(signal.id)}
                    >Ack</Button
                  >
                {/if}
                <Button size="sm" variant="outline" disabled={acting === signal.id} onclick={() => mute(signal.id)}
                  >Mute 1h</Button
                >
                <Button size="sm" disabled={acting === signal.id} onclick={() => resolve(signal.id)}>Resolve</Button>
              </Table.Cell>
            {/if}
          </Table.Row>
        {:else}
          <Table.Row>
            <Table.Cell colspan={showActions ? 7 : 6} class="text-center text-muted-foreground"
              >No signals.</Table.Cell
            >
          </Table.Row>
        {/each}
      </Table.Body>
    </Table.Root>
  </div>
{/snippet}

<div class="flex h-full flex-col gap-4 p-4 md:p-6">
  <div class="flex items-center justify-between">
    <h1 class="text-lg font-semibold">Signals</h1>
    <Select.Root type="single" bind:value={severityFilter}>
      <Select.Trigger class="w-40">
        {severityFilter === 'all' ? 'All severities' : severityFilter}
      </Select.Trigger>
      <Select.Content>
        <Select.Item value="all">All severities</Select.Item>
        <Select.Item value="critical">Critical</Select.Item>
        <Select.Item value="warning">Warning</Select.Item>
        <Select.Item value="info">Info</Select.Item>
      </Select.Content>
    </Select.Root>
  </div>

  <Tabs.Root value="open" class="flex flex-1 flex-col overflow-hidden">
    <Tabs.List>
      <Tabs.Trigger value="open">
        Open {#if open.length}<Badge variant="destructive" class="ml-1">{open.length}</Badge>{/if}
      </Tabs.Trigger>
      <Tabs.Trigger value="muted">Muted</Tabs.Trigger>
      <Tabs.Trigger value="resolved">Resolved</Tabs.Trigger>
    </Tabs.List>
    <Tabs.Content value="open" class="flex-1 overflow-auto">
      {@render signalTable(open, true)}
    </Tabs.Content>
    <Tabs.Content value="muted" class="flex-1 overflow-auto">
      {@render signalTable(muted, true)}
    </Tabs.Content>
    <Tabs.Content value="resolved" class="flex-1 overflow-auto">
      {@render signalTable(resolved, false)}
    </Tabs.Content>
  </Tabs.Root>
</div>
