import { CheckCircle2, Database, Film, FolderSearch, Gamepad2, Link2, ShieldAlert, Tv } from 'lucide-solid'
import { For, Show, createMemo, createSignal } from 'solid-js'
import { MediaCard } from '@/components/media/media-card'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card'
import { DataRow } from '@/components/ui/data-row'
import { EmptyState } from '@/components/ui/empty-state'
import { MetricCard } from '@/components/ui/metric-card'
import { mediaCatalog } from '@/services/mock-data'
import type { MediaItem } from '@/types/domain'
import { formatDate } from '@/utils/format'
import { mediaBadgeVariant, mediaTypeLabel } from '@/utils/media'

type MatchState = 'matched' | 'unmatched' | 'review'
type LibraryTab = 'all' | 'movies' | 'shows' | 'games'

interface LibraryEntry {
  id: string
  fileName: string
  absolutePath: string
  discoveredAt: string
  matchState: MatchState
  confidence: number
  media?: MediaItem
}

const entries: LibraryEntry[] = [
  {
    id: 'lib-1',
    fileName: 'Zero.Meridian.2026.2160p.HDR.mkv',
    absolutePath: '/mnt/library/movies/Zero Meridian (2026)/Zero.Meridian.2026.2160p.HDR.mkv',
    discoveredAt: '2026-03-10T10:18:00Z',
    matchState: 'matched',
    confidence: 0.96,
    media: mediaCatalog.find((item) => item.id === 9),
  },
  {
    id: 'lib-2',
    fileName: 'Abyss.Echo.S02E02.1080p.mkv',
    absolutePath: '/mnt/library/shows/Abyss Echo/Season 02/Abyss.Echo.S02E02.1080p.mkv',
    discoveredAt: '2026-03-10T10:22:00Z',
    matchState: 'matched',
    confidence: 0.93,
    media: mediaCatalog.find((item) => item.id === 17),
  },
  {
    id: 'lib-3',
    fileName: 'Star-Circuit-Zero-v1.0.iso',
    absolutePath: '/mnt/library/games/Star Circuit Zero/Star-Circuit-Zero-v1.0.iso',
    discoveredAt: '2026-03-10T10:31:00Z',
    matchState: 'review',
    confidence: 0.67,
    media: mediaCatalog.find((item) => item.id === 25),
  },
  {
    id: 'lib-4',
    fileName: 'Unknown.Release.CAM.avi',
    absolutePath: '/mnt/library/inbox/Unknown.Release.CAM.avi',
    discoveredAt: '2026-03-10T10:47:00Z',
    matchState: 'unmatched',
    confidence: 0.19,
  },
  {
    id: 'lib-5',
    fileName: 'Neon.Divide.2025.4K.REMUX.mkv',
    absolutePath: '/mnt/library/movies/Neon Divide (2025)/Neon.Divide.2025.4K.REMUX.mkv',
    discoveredAt: '2026-03-11T14:22:00Z',
    matchState: 'matched',
    confidence: 0.98,
    media: mediaCatalog.find((item) => item.id === 12),
  },
  {
    id: 'lib-6',
    fileName: 'Last.Light.Harbor.S01E07.1080p.mkv',
    absolutePath: '/mnt/library/shows/Last Light Harbor/Season 01/Last.Light.Harbor.S01E07.1080p.mkv',
    discoveredAt: '2026-03-11T15:05:00Z',
    matchState: 'matched',
    confidence: 0.91,
    media: mediaCatalog.find((item) => item.id === 14),
  },
  {
    id: 'lib-7',
    fileName: 'Ghostline.Kyoto-PS5.pkg',
    absolutePath: '/mnt/library/games/Ghostline Kyoto/Ghostline.Kyoto-PS5.pkg',
    discoveredAt: '2026-03-12T09:15:00Z',
    matchState: 'matched',
    confidence: 0.89,
    media: mediaCatalog.find((item) => item.id === 26),
  },
].filter((item): item is LibraryEntry => Boolean(item))

const stateTone = (state: MatchState): 'accent' | 'neutral' | 'secondary' => {
  if (state === 'matched') return 'accent'
  if (state === 'review') return 'neutral'
  return 'secondary'
}

const stateLabel = (state: MatchState): string => {
  if (state === 'matched') return 'Matched'
  if (state === 'review') return 'Needs review'
  return 'Unmatched'
}

export const LibraryPage = () => {
  const [activeTab, setActiveTab] = createSignal<LibraryTab>('all')

  const matched = createMemo(() => entries.filter((item) => item.matchState === 'matched'))
  const review = createMemo(() => entries.filter((item) => item.matchState === 'review'))
  const unmatched = createMemo(() => entries.filter((item) => item.matchState === 'unmatched'))
  const avgConfidence = createMemo(() =>
    Math.round((entries.reduce((acc, item) => acc + item.confidence, 0) / entries.length) * 100),
  )

  const filteredEntries = createMemo(() => {
    const tab = activeTab()
    if (tab === 'all') return matched()
    return matched().filter((entry) => entry.media?.type === (tab === 'movies' ? 'movie' : tab === 'shows' ? 'show' : 'game'))
  })

  const tabs: { id: LibraryTab; label: string; icon: typeof Film; count: number }[] = [
    { id: 'all', label: 'All', icon: Database, count: matched().length },
    { id: 'movies', label: 'Movies', icon: Film, count: matched().filter((e) => e.media?.type === 'movie').length },
    { id: 'shows', label: 'Shows', icon: Tv, count: matched().filter((e) => e.media?.type === 'show').length },
    { id: 'games', label: 'Games', icon: Gamepad2, count: matched().filter((e) => e.media?.type === 'game').length },
  ]

  return (
    <section class="space-y-8" data-testid="library-page">
      {/* Header */}
      <div class="animate-stagger space-y-6">
        <div class="flex items-center justify-between">
          <div>
            <h1 class="text-2xl font-semibold text-fg">Library</h1>
            <p class="text-sm text-muted-fg mt-1">Your indexed media collection</p>
          </div>
          <div class="flex items-center gap-2">
            <Button variant="subtle" size="sm">Start Scan</Button>
            <Button variant="primary" size="sm">Review Unmatched</Button>
          </div>
        </div>

        {/* Metrics */}
        <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
          <MetricCard
            icon={CheckCircle2}
            label="Matched"
            value={String(matched().length)}
            detail="linked files"
            tone="accent"
          />
          <MetricCard
            icon={ShieldAlert}
            label="Needs Review"
            value={String(review().length)}
            detail="low confidence"
          />
          <MetricCard
            icon={FolderSearch}
            label="Unmatched"
            value={String(unmatched().length)}
            detail="no metadata"
          />
          <MetricCard
            icon={Link2}
            label="Avg Confidence"
            value={`${avgConfidence()}%`}
            detail="match quality"
          />
        </div>
      </div>

      {/* Tabs */}
      <div class="flex items-center gap-1 rounded-xl bg-surface-container p-1">
        <For each={tabs}>
          {(tab) => {
            const Icon = tab.icon
            return (
              <button
                class={cn(
                  'flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-all',
                  activeTab() === tab.id
                    ? 'bg-surface-high text-fg shadow-sm'
                    : 'text-muted-fg hover:text-fg hover:bg-surface-high/50',
                )}
                onClick={() => setActiveTab(tab.id)}
              >
                <Icon class="h-4 w-4" />
                {tab.label}
                <span class={cn(
                  'rounded-full px-2 py-0.5 text-xs',
                  activeTab() === tab.id ? 'bg-primary/20 text-primary' : 'bg-surface-container-high text-muted-fg',
                )}>
                  {tab.count}
                </span>
              </button>
            )
          }}
        </For>
      </div>

      {/* Matched Grid */}
      <Show
        when={filteredEntries().length > 0}
        fallback={
          <Card>
            <CardContent class="py-12">
              <EmptyState
                title="No matched files"
                description="Run a scan to start indexing your media library."
              />
            </CardContent>
          </Card>
        }
      >
        <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
          <For each={filteredEntries()}>
            {(entry) => (
              <Show when={entry.media}>
                {(media) => (
                  <div class="space-y-2">
                    <MediaCard
                      item={media()}
                      subtitle={`${Math.round(entry.confidence * 100)}% confidence`}
                    />
                    <p class="line-clamp-1 text-xs text-muted-fg px-1">{entry.fileName}</p>
                  </div>
                )}
              </Show>
            )}
          </For>
        </div>
      </Show>

      {/* Review Queue */}
      <Show when={review().length + unmatched().length > 0}>
        <Card>
          <CardContent class="space-y-5 pt-6">
            <div class="flex items-center justify-between">
              <div>
                <h2 class="text-lg font-semibold text-fg">Review Queue</h2>
                <p class="text-sm text-muted-fg mt-1">Items needing manual attention</p>
              </div>
              <Badge variant="secondary">{review().length + unmatched().length} pending</Badge>
            </div>

            <div class="space-y-3">
              <For each={[...review(), ...unmatched()]}>
                {(entry) => (
                  <DataRow
                    tone={stateTone(entry.matchState)}
                    eyebrow={stateLabel(entry.matchState)}
                    title={entry.fileName}
                    description={entry.media ? `${entry.media.title} candidate` : 'No candidate match found'}
                    meta={`${Math.round(entry.confidence * 100)}% confidence · ${formatDate(entry.discoveredAt)}`}
                    badges={
                      entry.media ? (
                        <Badge variant={mediaBadgeVariant(entry.media.type)}>{mediaTypeLabel(entry.media.type)}</Badge>
                      ) : (
                        <Badge variant="secondary">Unresolved</Badge>
                      )
                    }
                    trailing={
                      <div class="flex h-10 w-10 items-center justify-center rounded-2xl border border-border bg-muted text-fg">
                        {entry.matchState === 'unmatched' ? (
                          <FolderSearch class="h-4 w-4" />
                        ) : (
                          <Database class="h-4 w-4" />
                        )}
                      </div>
                    }
                  />
                )}
              </For>
            </div>
          </CardContent>
        </Card>
      </Show>
    </section>
  )
}

function cn(...classes: (string | boolean | undefined)[]) {
  return classes.filter(Boolean).join(' ')
}
