import { Clock3, Gamepad2, Radar, RefreshCw, Search, Sparkles } from 'lucide-solid'
import { For, Show, createMemo, createResource, 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 { Input } from '@/components/ui/input'
import { MetricCard } from '@/components/ui/metric-card'
import { SectionHeading } from '@/components/ui/section-heading'
import { Skeleton } from '@/components/ui/skeleton'
import { gamesService } from '@/services/games-service'
import { searchService } from '@/services/search-service'
import { watchLaterService } from '@/services/watch-later-service'
import { useAuth } from '@/stores/auth-store'
import type { DiscoverSection, MediaItem, SearchResult } from '@/types/domain'
import { formatDate } from '@/utils/format'
import { mediaBadgeVariant, mediaTypeLabel } from '@/utils/media'

const sectionByKind = (sections: DiscoverSection[], kind: DiscoverSection['kind']) =>
  sections.find((section) => section.kind === kind)

const SearchResultRow = (props: {
  result: SearchResult
  queued: boolean
  busy: boolean
  onToggle: () => void
}) => (
  <DataRow
    tone={props.queued ? 'secondary' : 'accent'}
    eyebrow={`Score ${props.result.score}`}
    title={props.result.title}
    description={props.result.subtitle}
    badges={<Badge variant="neutral">Game</Badge>}
    trailing={
      <Button size="sm" variant={props.queued ? 'secondary' : 'primary'} disabled={props.busy} onClick={props.onToggle}>
        {props.busy ? 'Saving…' : props.queued ? 'Queued' : 'Add'}
      </Button>
    }
  />
)

export const GamesPage = () => {
  const auth = useAuth()
  const [reloadToken, setReloadToken] = createSignal(0)
  const [query, setQuery] = createSignal('')
  const [busyMediaId, setBusyMediaId] = createSignal<number | null>(null)
  const [actionError, setActionError] = createSignal<string | null>(null)

  const [gameSections, { refetch: refetchSections }] = createResource(reloadToken, () =>
    gamesService.getSections({ page: 1, pageSize: 4 }),
  )

  const [queueData, { refetch: refetchQueue }] = createResource(reloadToken, async () => {
    const accessToken = auth.accessToken()

    if (!accessToken) {
      return []
    }

    const items = await watchLaterService.getWatchLater(accessToken)
    return items.filter((item) => item.type === 'game')
  })

  const [searchResults] = createResource(
    () => query().trim(),
    async (term) => {
      if (term.length < 2) {
        return []
      }

      return searchService.search(term, { mediaType: 'game' })
    },
  )

  const queueItems = createMemo(() => queueData() ?? [])
  const queueIds = createMemo(() => new Set(queueItems().map((item) => item.id)))
  const anticipatedSection = createMemo(() => sectionByKind(gameSections() ?? [], 'most-anticipated-games'))
  const releasedSection = createMemo(() => sectionByKind(gameSections() ?? [], 'recently-released-games'))
  const indieSection = createMemo(() => sectionByKind(gameSections() ?? [], 'indie-highlights'))
  const trendingSection = createMemo(() => sectionByKind(gameSections() ?? [], 'trending'))
  const queueHours = createMemo(() =>
    Math.round(queueItems().reduce((total, item) => total + item.runtimeMinutes, 0) / 60),
  )
  const queryActive = createMemo(() => query().trim().length >= 2)

  const refresh = (): void => {
    setReloadToken((value) => value + 1)
  }

  const retryAll = (): void => {
    refetchSections()
    refetchQueue()
  }

  const toggleQueue = async (mediaId: number): Promise<void> => {
    const accessToken = auth.accessToken()

    if (!accessToken) {
      setActionError('Your session expired. Please sign in again.')
      return
    }

    setActionError(null)
    setBusyMediaId(mediaId)

    try {
      if (queueIds().has(mediaId)) {
        await watchLaterService.removeWatchLater(accessToken, mediaId)
      } else {
        await watchLaterService.addWatchLater(accessToken, mediaId)
      }

      refresh()
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Unable to update the backlog'
      setActionError(message)
    } finally {
      setBusyMediaId(null)
    }
  }

  const shelfRows = (items: MediaItem[] | undefined) => items?.slice(0, 4) ?? []

  return (
    <section class="space-y-6" data-testid="games-page">
      <Card class="animate-stagger">
        <CardContent class="space-y-6 pt-6">
          <SectionHeading
            eyebrow="Games"
            title="Keep the backlog lean and the launch radar readable."
            description="Search titles, save the good ones, and keep upcoming releases visible without letting the page sprawl."
            badge={<Badge variant="neutral">{queueItems().length} queued</Badge>}
            action={
              <Button variant="subtle" size="sm" onClick={retryAll}>
                <RefreshCw class="h-4 w-4" />
                Refresh
              </Button>
            }
          />

          <div class="grid gap-4 xl:grid-cols-[minmax(0,1fr)_320px]">
            <div class="relative">
              <Search class="pointer-events-none absolute left-4 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-fg" />
              <Input
                aria-label="Games search"
                placeholder="Search game titles, genres, and platforms"
                value={query()}
                onInput={(event) => setQuery(event.currentTarget.value)}
                class="h-12 pl-11"
              />
            </div>

            <div class="rounded-[1.5rem] border border-border bg-muted/45 px-4 py-4">
              <p class="text-[11px] font-semibold uppercase tracking-[0.24em] text-muted-fg">Control state</p>
              <p class="mt-2 text-sm text-fg">
                {queryActive()
                  ? `Searching for “${query().trim()}” while keeping queue actions one click away.`
                  : queueItems().length > 0
                    ? `${queueItems().length} queued games spanning about ${Math.max(1, queueHours())}h.`
                    : 'No backlog yet. Start with search or the launch radar below.'}
              </p>
            </div>
          </div>

          <div class="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
            <MetricCard
              icon={Gamepad2}
              label="Backlog"
              value={`${queueItems().length}`}
              detail={queueItems().length === 1 ? 'queued title' : 'queued titles'}
              tone="accent"
            />
            <MetricCard
              icon={Clock3}
              label="Playtime"
              value={queueItems().length > 0 ? `${Math.max(1, queueHours())}h` : '0h'}
              detail="estimated queue depth"
            />
            <MetricCard
              icon={Radar}
              label="On radar"
              value={`${anticipatedSection()?.items.length ?? 0}`}
              detail="tracked launches"
              tone="secondary"
            />
            <MetricCard
              icon={Sparkles}
              label="Indie picks"
              value={`${indieSection()?.items.length ?? 0}`}
              detail="smaller releases worth a look"
            />
          </div>

          <Show when={actionError()}>
            <div class="rounded-[1.4rem] border border-secondary/24 bg-secondary/10 px-4 py-3 text-sm text-fg">
              {actionError()}
            </div>
          </Show>
        </CardContent>
      </Card>

      <div class="grid gap-6 xl:grid-cols-[minmax(0,1.02fr)_380px]">
        <div class="space-y-6">
          <Card>
            <CardContent class="space-y-5 pt-6">
              <SectionHeading
                title="Queued Games"
                description="Titles already promoted into your backlog."
                badge={<Badge variant="accent">{queueItems().length} saved</Badge>}
              />

              <Show when={queueData.loading && queueItems().length === 0}>
                <div class="grid gap-4 md:grid-cols-2">
                  <For each={Array.from({ length: 4 }, (_, index) => index)}>{() => <Skeleton class="h-[280px]" />}</For>
                </div>
              </Show>

              <Show
                when={queueItems().length > 0}
                fallback={
                  <EmptyState
                    title="No backlog yet"
                    description="Save a few games from search or the launch radar to build your queue."
                  />
                }
              >
                <div class="grid gap-4 md:grid-cols-2">
                  <For each={queueItems().slice(0, 4)}>
                    {(item) => (
                      <div class="space-y-3">
                        <MediaCard item={item} />
                        <Button
                          size="sm"
                          variant="secondary"
                          disabled={busyMediaId() === item.id}
                          onClick={() => void toggleQueue(item.id)}
                        >
                          {busyMediaId() === item.id ? 'Saving…' : 'Remove from queue'}
                        </Button>
                      </div>
                    )}
                  </For>
                </div>
              </Show>
            </CardContent>
          </Card>

          <Show when={queryActive()}>
            <Card>
              <CardContent class="space-y-5 pt-6">
                <SectionHeading
                  title="Search Results"
                  description="Add titles directly from search without leaving the page."
                  badge={<Badge variant="neutral">{(searchResults() ?? []).length} matches</Badge>}
                />

                <Show when={searchResults.loading}>
                  <p class="text-sm text-muted-fg">Searching…</p>
                </Show>

                <Show
                  when={(searchResults() ?? []).length > 0}
                  fallback={
                    <Show when={!searchResults.loading}>
                      <EmptyState
                        title="Nothing matched"
                        description="Try a broader title or clear the search to return to the radar view."
                      />
                    </Show>
                  }
                >
                  <div class="space-y-3">
                    <For each={searchResults()}>
                      {(result) => (
                        <SearchResultRow
                          result={result}
                          queued={queueIds().has(result.id)}
                          busy={busyMediaId() === result.id}
                          onToggle={() => void toggleQueue(result.id)}
                        />
                      )}
                    </For>
                  </div>
                </Show>
              </CardContent>
            </Card>
          </Show>

          <Card>
            <CardContent class="space-y-5 pt-6">
              <SectionHeading
                title="Indie Highlights"
                description="Smaller games with sharper ideas."
                badge={<Badge variant="neutral">{indieSection()?.items.length ?? 0} loaded</Badge>}
              />

              <div class="grid gap-4 md:grid-cols-2">
                <For each={indieSection()?.items.slice(0, 4) ?? []}>
                  {(item) => <MediaCard item={item} subtitle={item.platforms.slice(0, 2).join(' • ')} />}
                </For>
              </div>
            </CardContent>
          </Card>
        </div>

        <div class="space-y-6">
          <Card>
            <CardContent class="space-y-5 pt-6">
              <SectionHeading
                title="Most Anticipated"
                description="Upcoming launches currently worth tracking."
                badge={<Badge variant="secondary">{anticipatedSection()?.items.length ?? 0} tracked</Badge>}
              />

              <div class="space-y-3">
                <For each={shelfRows(anticipatedSection()?.items)}>
                  {(item) => (
                    <DataRow
                      tone="secondary"
                      eyebrow="Launch radar"
                      title={item.title}
                      description={item.platforms.slice(0, 2).join(' • ')}
                      meta={formatDate(item.releaseDate)}
                      badges={<Badge variant={mediaBadgeVariant(item.type)}>{mediaTypeLabel(item.type)}</Badge>}
                      trailing={
                        <Button
                          size="sm"
                          variant={queueIds().has(item.id) ? 'secondary' : 'primary'}
                          disabled={busyMediaId() === item.id}
                          onClick={() => void toggleQueue(item.id)}
                        >
                          {busyMediaId() === item.id ? 'Saving…' : queueIds().has(item.id) ? 'Queued' : 'Add'}
                        </Button>
                      }
                    />
                  )}
                </For>
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardContent class="space-y-5 pt-6">
              <SectionHeading
                title="Recently Released"
                description="Fresh drops already live in the catalog."
                badge={<Badge variant="neutral">{releasedSection()?.items.length ?? 0} recent</Badge>}
              />

              <div class="space-y-3">
                <For each={shelfRows(releasedSection()?.items)}>
                  {(item) => (
                    <DataRow
                      tone="accent"
                      eyebrow="Recent release"
                      title={item.title}
                      description={item.platforms.slice(0, 2).join(' • ')}
                      meta={formatDate(item.releaseDate)}
                    />
                  )}
                </For>
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardContent class="space-y-5 pt-6">
              <SectionHeading
                title="Trending"
                description="Games spilling into the wider discover surface."
                badge={<Badge variant="neutral">{trendingSection()?.items.length ?? 0} active</Badge>}
              />

              <div class="space-y-3">
                <For each={shelfRows(trendingSection()?.items)}>
                  {(item) => (
                    <DataRow
                      tone="neutral"
                      eyebrow="Trending"
                      title={item.title}
                      description={item.genres.slice(0, 2).join(' • ')}
                      meta={formatDate(item.releaseDate)}
                    />
                  )}
                </For>
              </div>
            </CardContent>
          </Card>
        </div>
      </div>

      <Show when={gameSections.error || queueData.error}>
        <div class="rounded-[1.5rem] border border-secondary/24 bg-secondary/10 px-4 py-4 text-sm text-fg">
          {gameSections.error?.message ?? queueData.error?.message ?? 'Unable to load the games surface.'}
        </div>
      </Show>
    </section>
  )
}
