<script lang="ts">
  import type { Entity, EntityHealth } from '$lib/api'
  import { relativeTime } from '$lib/utils'
  import * as Table from '$lib/components/ui/table'
  import { Badge } from '$lib/components/ui/badge'
  import { Skeleton } from '$lib/components/ui/skeleton'
  import ArrowUpIcon from '@lucide/svelte/icons/arrow-up'
  import ArrowDownIcon from '@lucide/svelte/icons/arrow-down'
  import ArrowUpDownIcon from '@lucide/svelte/icons/arrow-up-down'

  let {
    entities,
    loading,
    selectedSlug = null,
    onSelect
  }: {
    entities: Entity[]
    loading: boolean
    selectedSlug?: string | null
    onSelect: (slug: string) => void
  } = $props()

  type SortKey = 'slug' | 'type' | 'name' | 'state' | 'health'
  let sortKey = $state<SortKey>('slug')
  let sortDir = $state<'asc' | 'desc'>('asc')

  function sortBy(key: SortKey) {
    if (sortKey === key) {
      sortDir = sortDir === 'asc' ? 'desc' : 'asc'
    } else {
      sortKey = key
      sortDir = 'asc'
    }
  }

  const healthRank: Record<EntityHealth, number> = { down: 0, degraded: 1, stale: 2, unknown: 3, healthy: 4 }

  function sortValue(entity: Entity, key: SortKey): string | number {
    if (key === 'health') return entity.health ? healthRank[entity.health] : -1
    return (entity[key] ?? '').toString().toLowerCase()
  }

  const sortedEntities = $derived.by(() => {
    const sorted = [...entities].sort((a, b) => {
      const av = sortValue(a, sortKey)
      const bv = sortValue(b, sortKey)
      if (av < bv) return -1
      if (av > bv) return 1
      return 0
    })
    if (sortDir === 'desc') sorted.reverse()
    return sorted
  })

  function stateVariant(state?: string | null): 'default' | 'secondary' | 'outline' {
    if (!state) return 'outline'
    if (state === 'active' || state === 'healthy') return 'default'
    return 'secondary'
  }

  const healthDot: Record<EntityHealth, string> = {
    healthy: 'bg-success',
    degraded: 'bg-warning',
    down: 'bg-destructive',
    stale: 'bg-warning/50',
    unknown: 'bg-muted-foreground/40'
  }

  function healthTitle(entity: Entity): string {
    if (!entity.health) return 'not monitored'
    if (entity.health === 'stale') return `stale — last checked ${relativeTime(entity.last_check_at)}`
    return `${entity.health} — checked ${relativeTime(entity.last_check_at)}`
  }

  // Widths vary per row so the skeleton reads as text, not a stack of identical bars.
  const skeletonSlugWidths = ['w-24', 'w-20', 'w-28', 'w-16', 'w-24', 'w-20', 'w-28', 'w-16']
  const skeletonNameWidths = ['w-32', 'w-40', 'w-24', 'w-36', 'w-28', 'w-40', 'w-24', 'w-32']
</script>

{#if loading}
  <div class="h-full min-h-0 overflow-hidden rounded-md border">
    <Table.Root>
      <Table.Header>
        <Table.Row>
          <Table.Head>Slug</Table.Head>
          <Table.Head>Type</Table.Head>
          <Table.Head>Name</Table.Head>
          <Table.Head>State</Table.Head>
          <Table.Head>Health</Table.Head>
        </Table.Row>
      </Table.Header>
      <Table.Body>
        {#each skeletonSlugWidths as slugWidth, i}
          <Table.Row class="hover:bg-transparent">
            <Table.Cell><Skeleton class="h-4 {slugWidth}" /></Table.Cell>
            <Table.Cell><Skeleton class="h-5 w-16 rounded-full" /></Table.Cell>
            <Table.Cell><Skeleton class="h-4 {skeletonNameWidths[i]}" /></Table.Cell>
            <Table.Cell><Skeleton class="h-5 w-14 rounded-full" /></Table.Cell>
            <Table.Cell>
              <div class="flex items-center gap-1.5">
                <Skeleton class="size-2 shrink-0 rounded-full" />
                <Skeleton class="h-4 w-12" />
              </div>
            </Table.Cell>
          </Table.Row>
        {/each}
      </Table.Body>
    </Table.Root>
  </div>
{:else}
  {#snippet sortHead(key: SortKey, label: string)}
    <Table.Head>
      <button type="button" class="flex items-center gap-1 hover:text-foreground" onclick={() => sortBy(key)}>
        {label}
        {#if sortKey === key}
          {#if sortDir === 'asc'}
            <ArrowUpIcon class="size-3" />
          {:else}
            <ArrowDownIcon class="size-3" />
          {/if}
        {:else}
          <ArrowUpDownIcon class="size-3 text-muted-foreground/50" />
        {/if}
      </button>
    </Table.Head>
  {/snippet}
  <div class="h-full min-h-0 overflow-auto rounded-md border">
    <Table.Root>
      <Table.Header>
        <Table.Row>
          {@render sortHead('slug', 'Slug')}
          {@render sortHead('type', 'Type')}
          {@render sortHead('name', 'Name')}
          {@render sortHead('state', 'State')}
          {@render sortHead('health', 'Health')}
        </Table.Row>
      </Table.Header>
      <Table.Body>
        {#each sortedEntities as entity (entity.id)}
          <Table.Row
            class="cursor-pointer {entity.slug === selectedSlug ? 'bg-muted' : ''}"
            role="button"
            tabindex={0}
            onclick={() => onSelect(entity.slug)}
            onkeydown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onSelect(entity.slug) } }}
          >
            <Table.Cell class="font-mono text-xs">{entity.slug}</Table.Cell>
            <Table.Cell><Badge variant="outline">{entity.type}</Badge></Table.Cell>
            <Table.Cell>{entity.name}</Table.Cell>
            <Table.Cell>
              {#if entity.state}
                <Badge variant={stateVariant(entity.state)}>{entity.state}</Badge>
              {:else}
                <span class="text-muted-foreground">—</span>
              {/if}
            </Table.Cell>
            <Table.Cell>
              {#if entity.health}
                <span class="flex items-center gap-1.5 text-xs" title={healthTitle(entity)}>
                  <span class="size-2 shrink-0 rounded-full {healthDot[entity.health]}"></span>
                  <span class="text-muted-foreground">{relativeTime(entity.last_check_at)}</span>
                </span>
              {:else}
                <span class="text-xs text-muted-foreground">—</span>
              {/if}
            </Table.Cell>
          </Table.Row>
        {:else}
          <Table.Row>
            <Table.Cell colspan={5} class="text-center text-muted-foreground"
              >No entities in this layer match the filter.</Table.Cell
            >
          </Table.Row>
        {/each}
      </Table.Body>
    </Table.Root>
  </div>
{/if}
