import { Film, Gamepad2, Play, Sparkles } from 'lucide-solid'
import { For, Show, createMemo, createResource, createSignal } from 'solid-js'
import { HeroCarousel } from '@/components/media/hero-carousel'
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 { Skeleton } from '@/components/ui/skeleton'
import { dashboardService } from '@/services/dashboard-service'
import { progressService } from '@/services/progress-service'
import { useAuth } from '@/stores/auth-store'
import type { ContinueWatchingItem, RecommendationItem } from '@/types/domain'
import { formatDate } from '@/utils/format'
import { mediaBadgeVariant, mediaTypeLabel } from '@/utils/media'

const cardSkeletons = (count: number) => Array.from({ length: count }, (_, index) => index)

export const DashboardPage = () => {
  const auth = useAuth()
  const [reloadToken, setReloadToken] = createSignal(0)
  const [progressBusyKey, setProgressBusyKey] = createSignal<string | null>(null)
  const [progressActionError, setProgressActionError] = createSignal<string | null>(null)

  const [dashboardData, { refetch: refetchDashboard }] = createResource(reloadToken, () =>
    dashboardService.getDashboard(),
  )

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

    if (!accessToken) {
      return []
    }

    return progressService.getContinueWatching(accessToken)
  })

  const dashboard = createMemo(() => dashboardData())
  const continueEntries = createMemo(() => continueWatchingData() ?? [])
  const recommendations = createMemo(() => dashboard()?.recommendations ?? [])
  const trending = createMemo(() => dashboard()?.trending ?? [])
  const upcoming = createMemo(() => dashboard()?.upcoming ?? [])
  const watchLater = createMemo(() => dashboard()?.watchLater ?? [])
  const gameBacklog = createMemo(() => dashboard()?.gameBacklog ?? [])
  
  const averageRecommendationScore = createMemo(() => {
    const items = recommendations()

    if (items.length === 0) {
      return null
    }

    return Math.round(items.reduce((total, entry) => total + entry.score, 0) / items.length)
  })

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

  const retryAll = (): void => {
    refetchDashboard()
    refetchContinue()
  }

  const updateEntryProgress = async (entry: ContinueWatchingItem, nextPercent: number): Promise<void> => {
    const accessToken = auth.accessToken()

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

    const busyKey = `${entry.item.id}:${entry.progress.episodeNumber}:${nextPercent}`
    setProgressBusyKey(busyKey)
    setProgressActionError(null)

    try {
      await progressService.updateProgress(accessToken, {
        mediaId: entry.item.id,
        seasonNumber: entry.progress.seasonNumber,
        episodeNumber: entry.progress.episodeNumber,
        progressPercent: nextPercent,
      })
      refresh()
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Unable to update playback progress'
      setProgressActionError(message)
    } finally {
      setProgressBusyKey(null)
    }
  }

  const recommendationMeta = (entry: RecommendationItem): string =>
    `${mediaTypeLabel(entry.media.type)} · ${entry.media.genres.slice(0, 2).join(' • ')}`

  return (
    <section class="space-y-12" data-testid="dashboard-page">
      {/* Hero Carousel */}
      <Show when={trending().length > 0}>
        <div class="animate-brutal-appear border-4 border-primary shadow-brutal-lg">
          <HeroCarousel items={trending().slice(0, 5)} autoplay loop />
        </div>
      </Show>

      <div class="space-y-10">
        {/* MASSIVE PAGE HEADER */}
        <div class="flex items-end justify-between animate-brutal-appear border-b-4 border-primary pb-6">
          <div>
            <h1 class="text-6xl sm:text-8xl font-bold text-fg tracking-tighter uppercase leading-none">
              WELCOME<br/>BACK
            </h1>
            <p class="text-sm text-primary mt-4 uppercase tracking-[0.2em] font-mono font-bold">// YOUR MEDIA UNIVERSE</p>
          </div>
          <Button variant="secondary" size="md" onClick={refresh} class="hidden sm:flex">
            REFRESH
          </Button>
        </div>

        {/* BRUTAL STATS GRID */}
        <div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
          <MetricCard
            icon={Play}
            label="Continue Watching"
            value={String(continueEntries().length)}
            detail={continueEntries().length === 1 ? 'title' : 'titles'}
            tone="accent"
          />
          <MetricCard
            icon={Sparkles}
            label="Recommendations"
            value={averageRecommendationScore() ? `${averageRecommendationScore()}%` : '—'}
            detail={recommendations().length > 0 ? `${recommendations().length} picks` : 'analyzing'}
          />
          <MetricCard
            icon={Film}
            label="Watch Later"
            value={String(watchLater().length)}
            detail="queued titles"
          />
          <MetricCard
            icon={Gamepad2}
            label="Game Backlog"
            value={String(gameBacklog().length)}
            detail="to play"
          />
        </div>

        <Show when={progressActionError()}>
          <div class="bg-danger border-4 border-danger px-6 py-4 text-sm text-on-danger font-bold uppercase tracking-wide shadow-brutal">
            {progressActionError()}
          </div>
        </Show>
      </div>

      {/* CONTINUE WATCHING SECTION */}
      <Card class="animate-brutal-appear">
        <CardContent class="space-y-8 pt-8">
          <div class="flex items-center justify-between border-b-4 border-outline pb-4">
            <div>
              <h2 class="text-4xl font-bold text-fg tracking-tighter uppercase">CONTINUE</h2>
              <p class="text-xs text-muted-fg mt-2 uppercase tracking-wider font-mono">// PICK UP WHERE YOU LEFT OFF</p>
            </div>
            <Show when={continueEntries().length > 0}>
              <Badge variant="accent" class="text-xs px-4 py-2">{continueEntries().length} ACTIVE</Badge>
            </Show>
          </div>

          <Show when={continueWatchingData.loading && continueEntries().length === 0}>
            <div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
              <For each={cardSkeletons(3)}>{() => <Skeleton class="h-80 border-4 border-outline" />}</For>
            </div>
          </Show>

          <Show
            when={continueEntries().length > 0}
            fallback={
              <EmptyState
                title="NOTHING IN PROGRESS"
                description="Start watching something and it'll appear here."
              />
            }
          >
            <div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
              <For each={continueEntries().slice(0, 6)}>
                {(entry) => {
                  const resumeKey = () => `${entry.item.id}:${entry.progress.episodeNumber}:${Math.min(99, entry.progress.progressPercent + 15)}`

                  return (
                    <div class="space-y-4 group">
                      <MediaCard
                        item={entry.item}
                        progressPercent={entry.progress.progressPercent}
                        subtitle={`S${entry.progress.seasonNumber} E${entry.progress.episodeNumber} · ${formatDate(entry.progress.lastWatchedAt)}`}
                      />
                      <Button
                        size="md"
                        variant="primary"
                        class="w-full"
                        disabled={progressBusyKey() === resumeKey()}
                        onClick={() =>
                          void updateEntryProgress(
                            entry,
                            Math.min(99, entry.progress.progressPercent + 15),
                          )
                        }
                      >
                        {progressBusyKey() === resumeKey() ? 'UPDATING…' : 'RESUME'}
                      </Button>
                    </div>
                  )
                }}
              </For>
            </div>
          </Show>
        </CardContent>
      </Card>

      {/* RECOMMENDATIONS SECTION */}
      <Card class="animate-brutal-appear">
        <CardContent class="space-y-8 pt-8">
          <div class="flex items-center justify-between border-b-4 border-outline pb-4">
            <div>
              <h2 class="text-4xl font-bold text-fg tracking-tighter uppercase">RECOMMENDED</h2>
              <p class="text-xs text-muted-fg mt-2 uppercase tracking-wider font-mono">// CURATED FOR YOUR TASTE</p>
            </div>
            <Show when={recommendations().length > 0}>
              <Badge variant="neutral" class="text-xs px-4 py-2">{recommendations().length} PICKS</Badge>
            </Show>
          </div>

          <Show when={dashboardData.loading && recommendations().length === 0}>
            <div class="space-y-4">
              <For each={cardSkeletons(3)}>{() => <Skeleton class="h-28 border-4 border-outline" />}</For>
            </div>
          </Show>

          <Show
            when={recommendations().length > 0}
            fallback={
              <EmptyState
                title="NO RECOMMENDATIONS YET"
                description="Watch more content to get personalized suggestions."
              />
            }
          >
            <div class="space-y-4">
              <For each={recommendations().slice(0, 4)}>
                {(entry) => (
                  <DataRow
                    tone={mediaBadgeVariant(entry.media.type)}
                    eyebrow={`MATCH ${entry.score}%`}
                    title={entry.media.title}
                    description={entry.reason}
                    meta={recommendationMeta(entry)}
                    badges={
                      <Badge variant={mediaBadgeVariant(entry.media.type)}>
                        {mediaTypeLabel(entry.media.type)}
                      </Badge>
                    }
                  />
                )}
              </For>
            </div>
          </Show>
        </CardContent>
      </Card>

      {/* UPCOMING RELEASES */}
      <Show when={upcoming().length > 0}>
        <Card class="animate-brutal-appear">
          <CardContent class="space-y-8 pt-8">
            <div class="flex items-center justify-between border-b-4 border-outline pb-4">
              <div>
                <h2 class="text-4xl font-bold text-fg tracking-tighter uppercase">UPCOMING</h2>
                <p class="text-xs text-muted-fg mt-2 uppercase tracking-wider font-mono">// ON YOUR RADAR</p>
              </div>
              <Badge variant="secondary" class="text-xs px-4 py-2">{upcoming().length} TITLES</Badge>
            </div>

            <div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
              <For each={upcoming().slice(0, 4)}>
                {(item) => (
                  <MediaCard
                    item={item}
                    subtitle={`${mediaTypeLabel(item.type)} · ${item.genres.slice(0, 2).join(' • ')}`}
                  />
                )}
              </For>
            </div>
          </CardContent>
        </Card>
      </Show>

      {/* ERROR STATE */}
      <Show when={dashboardData.error || continueWatchingData.error}>
        <div class="flex items-center justify-between bg-danger border-4 border-danger px-6 py-4 text-sm text-on-danger font-bold uppercase tracking-wide shadow-brutal">
          <span>
            {dashboardData.error?.message ?? continueWatchingData.error?.message ?? 'UNABLE TO LOAD DASHBOARD'}
          </span>
          <Button size="sm" variant="secondary" onClick={retryAll}>
            RETRY
          </Button>
        </div>
      </Show>
    </section>
  )
}
