<script lang="ts">
  import { onMount } from 'svelte'
  import { fetchDashboardSummary, type DashboardSummary } from '$lib/api'
  import { liveEvents, subscribeEvents, type OikosEvent } from '$lib/stores/events'
  import * as Card from '$lib/components/ui/card'
  import { Badge } from '$lib/components/ui/badge'
  import { Skeleton } from '$lib/components/ui/skeleton'
  import { ScrollArea } from '$lib/components/ui/scroll-area'
  import CircleCheckIcon from '@lucide/svelte/icons/circle-check'
  import TriangleAlertIcon from '@lucide/svelte/icons/triangle-alert'
  import OctagonXIcon from '@lucide/svelte/icons/octagon-x'

  let summary = $state<DashboardSummary | null>(null)
  let loading = $state(true)

  async function load() {
    summary = await fetchDashboardSummary()
    loading = false
  }

  onMount(() => {
    load()
    const unsubscribe = subscribeEvents()
    const interval = setInterval(load, 15000)
    return () => {
      unsubscribe()
      clearInterval(interval)
    }
  })

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

  const degradedTypes = $derived(
    summary
      ? [
          { label: 'Degraded', count: summary.health.degraded, tone: 'text-warning' as const },
          { label: 'Down', count: summary.health.down, tone: 'text-destructive' as const }
        ].filter((t) => t.count > 0)
      : []
  )

  const maxEventRate = $derived(
    summary?.event_rate.length ? Math.max(...summary.event_rate.map((b) => b.count), 1) : 1
  )

  function formatEventLabel(ev: OikosEvent) {
    return ev.type
  }

  const totalEntities = $derived(
    summary ? Object.values(summary.entities_by_type).reduce((a, b) => a + b, 0) : 0
  )
  const topTypes = $derived(
    summary
      ? Object.entries(summary.entities_by_type)
          .sort((a, b) => b[1] - a[1])
          .slice(0, 3)
      : []
  )
  const entityTypeCount = $derived(summary ? Object.keys(summary.entities_by_type).length : 0)

  const totalMonitored = $derived(
    summary
      ? summary.health.healthy + summary.health.degraded + summary.health.down + summary.health.unknown
      : 0
  )
  const healthTone = $derived(
    !summary ? 'ok' : summary.health.down > 0 ? 'down' : summary.health.degraded > 0 ? 'degraded' : 'ok'
  )

  const totalSignals = $derived(
    summary ? Object.values(summary.signals_by_severity).reduce((a, b) => a + b, 0) : 0
  )
  const worstSeverity = $derived(
    summary?.signals_by_severity.critical
      ? 'critical'
      : summary?.signals_by_severity.warning
        ? 'warning'
        : 'none'
  )

  const executionsRunning = $derived(summary?.executions_by_state.running ?? 0)
  const executionsFailed = $derived(summary?.executions_by_state.failed ?? 0)
</script>

<div class="@container/main flex h-full flex-col gap-4 overflow-y-auto p-4 md:p-6">
  <h1 class="text-lg font-semibold">Overview</h1>

  {#if loading}
    <div class="grid grid-cols-2 gap-4 md:grid-cols-4">
      {#each Array(4) as _}
        <Skeleton class="h-28 w-full" />
      {/each}
    </div>
  {:else if summary}
    <div
      class="*:data-[slot=card]:from-primary/5 *:data-[slot=card]:to-card dark:*:data-[slot=card]:bg-card grid grid-cols-1 gap-4 *:data-[slot=card]:bg-gradient-to-t *:data-[slot=card]:shadow-xs @xl/main:grid-cols-2 @5xl/main:grid-cols-4"
    >
      <Card.Root class="@container/card">
        <Card.Header>
          <Card.Description>Entities</Card.Description>
          <Card.Title class="text-2xl font-semibold tabular-nums @[250px]/card:text-3xl">
            {totalEntities}
          </Card.Title>
          <Card.Action>
            <Badge variant="outline">{entityTypeCount} types</Badge>
          </Card.Action>
        </Card.Header>
        <Card.Footer class="flex-col items-start gap-1.5 text-sm">
          <div class="line-clamp-1 flex flex-wrap gap-x-1.5 font-medium">
            {#each topTypes as [type, count]}
              <span class="text-muted-foreground">{type}: <span class="text-foreground">{count}</span></span>
            {/each}
          </div>
          <div class="text-muted-foreground">Across the fleet</div>
        </Card.Footer>
      </Card.Root>

      <Card.Root class="@container/card">
        <Card.Header>
          <Card.Description>Fleet health</Card.Description>
          <Card.Title class="text-2xl font-semibold tabular-nums @[250px]/card:text-3xl">
            {summary.health.healthy} / {totalMonitored}
          </Card.Title>
          <Card.Action>
            {#if healthTone === 'ok'}
              <Badge variant="outline"><CircleCheckIcon class="text-success" />healthy</Badge>
            {:else if healthTone === 'degraded'}
              <Badge variant="outline"><TriangleAlertIcon class="text-warning" />degraded</Badge>
            {:else}
              <Badge variant="outline"><OctagonXIcon class="text-destructive" />down</Badge>
            {/if}
          </Card.Action>
        </Card.Header>
        <Card.Footer class="flex-col items-start gap-1.5 text-sm">
          <div class="line-clamp-1 flex gap-2 font-medium">
            {summary.health.degraded} degraded · {summary.health.down} down · {summary.health.unknown} unmonitored
          </div>
          <div class="text-muted-foreground">Healthy entities as observed by the scheduler</div>
        </Card.Footer>
      </Card.Root>

      <Card.Root class="@container/card">
        <Card.Header>
          <Card.Description>Open signals</Card.Description>
          <Card.Title class="text-2xl font-semibold tabular-nums @[250px]/card:text-3xl">
            {totalSignals}
          </Card.Title>
          <Card.Action>
            {#if worstSeverity === 'critical'}
              <Badge variant="destructive"><TriangleAlertIcon />critical</Badge>
            {:else if worstSeverity === 'warning'}
              <Badge variant="secondary"><TriangleAlertIcon />warning</Badge>
            {:else}
              <Badge variant="outline"><CircleCheckIcon class="text-success" />clear</Badge>
            {/if}
          </Card.Action>
        </Card.Header>
        <Card.Footer class="flex-col items-start gap-1.5 text-sm">
          <div class="line-clamp-1 flex flex-wrap gap-x-1.5 font-medium">
            {#each Object.entries(summary.signals_by_severity) as [severity, count]}
              <span class="text-muted-foreground">{severity}: <span class="text-foreground">{count}</span></span>
            {/each}
          </div>
          <div class="text-muted-foreground">Unresolved right now</div>
        </Card.Footer>
      </Card.Root>

      <Card.Root class="@container/card">
        <Card.Header>
          <Card.Description>Pending approvals</Card.Description>
          <Card.Title class="text-2xl font-semibold tabular-nums @[250px]/card:text-3xl">
            {summary.approvals_pending}
          </Card.Title>
          <Card.Action>
            {#if summary.approvals_pending > 0}
              <Badge variant="destructive">needs review</Badge>
            {:else}
              <Badge variant="outline"><CircleCheckIcon class="text-success" />clear</Badge>
            {/if}
          </Card.Action>
        </Card.Header>
        <Card.Footer class="flex-col items-start gap-1.5 text-sm">
          <div class="line-clamp-1 flex gap-2 font-medium">
            {executionsRunning} running · {executionsFailed} failed
          </div>
          <div class="text-muted-foreground">Executions in the last 24h</div>
        </Card.Footer>
      </Card.Root>
    </div>

    {#if degradedTypes.length}
      <Card.Root>
        <Card.Header>
          <Card.Title class="text-sm">Attention needed</Card.Title>
        </Card.Header>
        <Card.Content class="flex gap-2">
          {#each degradedTypes as t}
            <Badge variant={t.tone === 'text-destructive' ? 'destructive' : 'secondary'}
              >{t.label}: {t.count}</Badge
            >
          {/each}
        </Card.Content>
      </Card.Root>
    {/if}

    <Card.Root>
      <Card.Header>
        <Card.Title class="text-sm">Event rate (6h, 5m buckets)</Card.Title>
      </Card.Header>
      <Card.Content>
        <div class="flex h-16 items-end gap-0.5">
          {#each summary.event_rate as bucket}
            <div
              class="flex-1 rounded-t bg-primary/60"
              style="height: {Math.max((bucket.count / maxEventRate) * 100, 2)}%"
              title="{bucket.bucket}: {bucket.count} events"
            ></div>
          {/each}
        </div>
      </Card.Content>
    </Card.Root>
  {/if}

  <Card.Root class="flex-1">
    <Card.Header>
      <Card.Title class="text-sm">Live event ticker</Card.Title>
    </Card.Header>
    <Card.Content class="p-0">
      <ScrollArea class="h-64 px-4 pb-4">
        <div class="flex flex-col gap-1">
          {#each $liveEvents as ev (ev.id)}
            <div class="flex items-center gap-2 text-xs">
              <Badge variant={severityVariant(ev.severity)} class="shrink-0"
                >{ev.severity}</Badge
              >
              <span class="font-mono text-muted-foreground">{new Date(ev.ts).toLocaleTimeString()}</span>
              <span>{formatEventLabel(ev)}</span>
              <span class="truncate text-muted-foreground">{ev.source}</span>
            </div>
          {:else}
            <p class="text-xs text-muted-foreground">Waiting for events…</p>
          {/each}
        </div>
      </ScrollArea>
    </Card.Content>
  </Card.Root>
</div>
