import { useEffect, useMemo, useRef, useState } from 'react'
import {
  Alert,
  Badge,
  Button,
  Card,
  Container,
  Divider,
  Grid,
  Group,
  Image,
  Loader,
  Modal,
  Paper,
  SegmentedControl,
  Skeleton,
  Stack,
  Text,
  TextInput,
  Title,
} from '@mantine/core'
import {
  IconAlertCircle,
  IconChartBar,
  IconDeviceTv,
  IconLayoutDashboard,
  IconMovie,
  IconSearch,
  IconSortAscendingLetters,
  IconX,
} from '@tabler/icons-react'
import './movies-page.css'

type ContentType = 'movie' | 'tvshow'
type SortBy = 'title' | 'year'
const WEB_API_KEY = import.meta.env.VITE_WEB_API_KEY ?? 'web-dev-key-change-me'
const ADMIN_API_KEY = import.meta.env.VITE_ADMIN_API_KEY ?? 'admin-dev-key-change-me'
type RealtimeContentAction = 'created' | 'updated' | 'deleted'
const MIN_BUTTON_LOADING_MS = 420

interface SocketClient {
  on: (event: string, handler: (...args: unknown[]) => void) => void
  off: (event: string, handler: (...args: unknown[]) => void) => void
  disconnect: () => void
}

declare global {
  interface Window {
    io?: (url?: string, options?: Record<string, unknown>) => SocketClient
  }
}

interface ContentListItem {
  title: string
  year: number | null
  plot: string | null
  ageRating: string | null
  type: ContentType
  genres: string[]
  cast?: string[]
  backdrop: string | null
  currentSeason: number | null
}

interface ContentListResponse {
  success: boolean
  data?: ContentListItem[]
  error?: {
    message: string
  }
}

interface ContentRealtimeEvent {
  action: RealtimeContentAction
  url: string
  content?: ContentListItem
  occurredAt: string
}

interface AdminOverview {
  generatedAt: string
  environment: 'development' | 'production' | 'test'
  cache: {
    configuredTtlSeconds: number
    keyCount: number
    analyzedKeyLimit: number
    sampled: boolean
    totalBytes: number
    redisMemory: {
      usedBytes: number
      maxBytes: number | null
    }
    ttlDistribution: {
      expiredOrNoTtl: number
      lessThan5Min: number
      min5To30: number
      min30Plus: number
    }
    expiringSoon: Array<{
      key: string
      mediaTitle?: string | null
      cachedAt?: number | null
      ttlSeconds: number
    }>
  }
  content: {
    total: number
    byType: {
      movie: number
      tvshow: number
    }
    addedLast24h: number
    addedLast7d: number
    metadataGaps: {
      missingPlot: number
      missingAgeRating: number
      missingBackdrop: number
    }
    topGenres: Array<{
      name: string
      count: number
    }>
  }
  jobs: {
    counts: {
      pending: number
      processing: number
      completed: number
      failed: number
    }
    averageDurationMs: number
    failedRecent: Array<{
      id: string
      url: string
      error: string
      updatedAt: string
    }>
  }
  requestMetrics: {
    cacheHits: number
    cacheMisses: number
    cacheHitRate: number
    sourceCounts: {
      cache: number
      database: number
      netflix: number
    }
  }
}

interface AdminOverviewResponse {
  success: boolean
  data?: AdminOverview
  error?: {
    message: string
  }
}

function formatTtl(ttlSeconds: number): string {
  if (ttlSeconds < 60) return `${ttlSeconds}s`
  if (ttlSeconds < 3600) return `${Math.ceil(ttlSeconds / 60)}dk`
  if (ttlSeconds < 86400) {
    const hours = Math.floor(ttlSeconds / 3600)
    const minutes = Math.floor((ttlSeconds % 3600) / 60)
    return minutes > 0 ? `${hours}sa ${minutes}dk` : `${hours}sa`
  }

  const days = Math.floor(ttlSeconds / 86400)
  const hours = Math.floor((ttlSeconds % 86400) / 3600)
  return hours > 0 ? `${days}g ${hours}sa` : `${days}g`
}

function formatBytes(value: number): string {
  if (!Number.isFinite(value) || value <= 0) return '0 B'
  const units = ['B', 'KB', 'MB', 'GB', 'TB']
  let size = value
  let unitIndex = 0
  while (size >= 1024 && unitIndex < units.length - 1) {
    size /= 1024
    unitIndex += 1
  }
  const decimals = size >= 10 ? 0 : 1
  return `${size.toFixed(decimals)} ${units[unitIndex]}`
}

async function waitForMinimumDuration(startedAt: number, minMs: number): Promise<void> {
  const elapsed = Date.now() - startedAt
  const remaining = minMs - elapsed
  if (remaining > 0) {
    await new Promise<void>((resolve) => setTimeout(resolve, remaining))
  }
}

function getContentKey(item: Pick<ContentListItem, 'type' | 'title' | 'year'>): string {
  return `${item.type}::${item.title}::${item.year ?? 'na'}`
}

async function loadSocketClient(): Promise<SocketClient | null> {
  if (typeof window === 'undefined') return null
  if (window.io) {
    return window.io('/', { transports: ['websocket', 'polling'] })
  }

  await new Promise<void>((resolve, reject) => {
    const existing = document.querySelector<HTMLScriptElement>('script[data-socket-io-client="1"]')
    if (existing && window.io) {
      resolve()
      return
    }

    if (existing) {
      existing.addEventListener('load', () => resolve(), { once: true })
      existing.addEventListener('error', () => reject(new Error('Failed to load socket client')), { once: true })
      return
    }

    const script = document.createElement('script')
    script.src = '/socket.io/socket.io.js'
    script.async = true
    script.dataset.socketIoClient = '1'
    script.onload = () => resolve()
    script.onerror = () => reject(new Error('Failed to load socket client'))
    document.head.appendChild(script)
  })

  const ioClient = (window as unknown as {
    io?: (url?: string, options?: Record<string, unknown>) => SocketClient
  }).io
  if (typeof ioClient !== 'function') return null
  return ioClient('/', { transports: ['websocket', 'polling'] })
}

function BackdropImage({ src, alt }: { src: string; alt: string }) {
  const [loaded, setLoaded] = useState(false)

  return (
    <div className="image-shell">
      {!loaded && <Skeleton height={190} radius={0} className="image-skeleton" />}
      <Image
        src={src}
        alt={alt}
        h={190}
        className={`lazy-image ${loaded ? 'is-loaded' : ''}`}
        onLoad={() => setLoaded(true)}
        loading="lazy"
        decoding="async"
      />
    </div>
  )
}

export function MoviesPage() {
  const [activeView, setActiveView] = useState<'catalog' | 'admin'>('catalog')
  const [items, setItems] = useState<ContentListItem[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [adminOverview, setAdminOverview] = useState<AdminOverview | null>(null)
  const [adminLoading, setAdminLoading] = useState(true)
  const [adminRefreshing, setAdminRefreshing] = useState(false)
  const [adminError, setAdminError] = useState<string | null>(null)
  const [adminActionMessage, setAdminActionMessage] = useState<string | null>(null)
  const [adminActionPending, setAdminActionPending] = useState<string | null>(null)
  const [typeFilter, setTypeFilter] = useState<'all' | ContentType>('all')
  const [search, setSearch] = useState('')
  const [sortBy, setSortBy] = useState<SortBy>('title')
  const [activeGenre, setActiveGenre] = useState<string | null>(null)
  const [flashItemKeys, setFlashItemKeys] = useState<string[]>([])
  const [pinnedNewItemKeys, setPinnedNewItemKeys] = useState<string[]>([])
  const [flashTtlKeys, setFlashTtlKeys] = useState<string[]>([])
  const [selectedContentKey, setSelectedContentKey] = useState<string | null>(null)
  const typeFilterRef = useRef<'all' | ContentType>(typeFilter)
  const hasLoadedAdminRef = useRef(false)
  const previousTtlKeysRef = useRef<string[]>([])

  useEffect(() => {
    typeFilterRef.current = typeFilter
  }, [typeFilter])

  useEffect(() => {
    if (!adminActionMessage) return
    const timer = setTimeout(() => {
      setAdminActionMessage(null)
    }, 2600)
    return () => clearTimeout(timer)
  }, [adminActionMessage])

  useEffect(() => {
    if (activeView !== 'catalog') return
    if (flashItemKeys.length === 0) return

    const timer = setTimeout(() => {
      setFlashItemKeys([])
    }, 1900)

    return () => clearTimeout(timer)
  }, [activeView, flashItemKeys])

  useEffect(() => {
    if (flashTtlKeys.length === 0) return
    const timer = setTimeout(() => {
      setFlashTtlKeys([])
    }, 1800)
    return () => clearTimeout(timer)
  }, [flashTtlKeys])

  const loadAdminOverview = async (signal?: AbortSignal, background = false) => {
    const isInitialLoad = !hasLoadedAdminRef.current && !background
    if (isInitialLoad) {
      setAdminLoading(true)
      setAdminRefreshing(false)
      setAdminError(null)
    } else if (!background) {
      setAdminRefreshing(true)
      setAdminError(null)
    }
    try {
      const response = await fetch('/api/admin/overview', {
        method: 'GET',
        headers: {
          'X-API-Key': ADMIN_API_KEY,
        },
        signal,
      })

      const data: AdminOverviewResponse = await response.json()
      if (data.success && data.data) {
        setAdminOverview(data.data)
        hasLoadedAdminRef.current = true
        return
      }

      if (!background) {
        setAdminError(data.error?.message || 'Dashboard verileri alınamadı')
      }
    } catch {
      if (!signal?.aborted && !background) {
        setAdminError('Dashboard bağlantı hatası')
      }
    } finally {
      if (!signal?.aborted) {
        if (isInitialLoad) {
          setAdminLoading(false)
        } else if (!background) {
          setAdminRefreshing(false)
        }
      }
    }
  }

  const loadContent = async (
    signal?: AbortSignal,
    background = false,
    filter: 'all' | ContentType = typeFilterRef.current
  ) => {
    if (!background) {
      setLoading(true)
      setError(null)
    }
    try {
      const params = new URLSearchParams()
      params.append('limit', '100')
      if (filter !== 'all') {
        params.append('type', filter)
      }

      const response = await fetch(`/api/content?${params.toString()}`, {
        method: 'GET',
        headers: {
          'X-API-Key': WEB_API_KEY,
        },
        signal,
      })

      const data: ContentListResponse = await response.json()
      if (data.success && data.data) {
        setItems(data.data)
        return
      }

      if (!background) {
        setError(data.error?.message || 'Liste alınamadı')
      }
    } catch {
      if (!signal?.aborted && !background) {
        setError('Bağlantı hatası')
      }
    } finally {
      if (!signal?.aborted && !background) {
        setLoading(false)
      }
    }
  }

  useEffect(() => {
    const controller = new AbortController()
    void loadAdminOverview(controller.signal)
    return () => controller.abort()
  }, [])

  const runAdminAction = async (
    actionKey: string,
    endpoint: string,
    body?: Record<string, unknown>
  ) => {
    const startedAt = Date.now()
    setAdminActionPending(actionKey)
    setAdminActionMessage(null)
    setAdminError(null)
    try {
      const response = await fetch(endpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': ADMIN_API_KEY,
        },
        body: body ? JSON.stringify(body) : undefined,
      })

      const result = (await response.json()) as {
        success: boolean
        data?: { queued: number; skipped: number; details?: string }
        error?: { message: string }
      }

      if (!result.success || !result.data) {
        setAdminError(result.error?.message || 'Admin aksiyonu basarisiz')
        return
      }

      setAdminActionMessage(
        `${result.data.details ?? 'Aksiyon tamamlandi'} | queued: ${result.data.queued}, skipped: ${result.data.skipped}`
      )
      await loadAdminOverview(undefined, true)
    } catch {
      setAdminError('Admin aksiyonu baglanti hatasi')
    } finally {
      await waitForMinimumDuration(startedAt, MIN_BUTTON_LOADING_MS)
      setAdminActionPending(null)
    }
  }

  const handleAdminRefresh = async () => {
    const startedAt = Date.now()
    await loadAdminOverview(undefined, false)
    await waitForMinimumDuration(startedAt, MIN_BUTTON_LOADING_MS)
  }

  useEffect(() => {
    const controller = new AbortController()
    void loadContent(controller.signal, false, typeFilter)

    return () => controller.abort()
  }, [typeFilter])

  useEffect(() => {
    let socket: SocketClient | null = null
    let adminRefreshTimer: ReturnType<typeof setTimeout> | null = null

    const scheduleAdminRefresh = () => {
      if (adminRefreshTimer) return
      adminRefreshTimer = setTimeout(() => {
        adminRefreshTimer = null
        void loadAdminOverview(undefined, true)
      }, 220)
    }

    const attachSocket = async () => {
      try {
        socket = await loadSocketClient()
        if (!socket) return

        const onConnect = () => {
          void loadContent(undefined, true, typeFilterRef.current)
          void loadAdminOverview(undefined, true)
        }

        const onContentEvent = (...args: unknown[]) => {
          const event = args[0] as ContentRealtimeEvent | undefined
          if (!event) return

          if (event.action === 'deleted') {
            void loadContent(undefined, true, typeFilterRef.current)
            return
          }

          if (!event.content) return
          const incoming = event.content
          const incomingKey = getContentKey(incoming)
          setItems((prev) => {
            const next = [...prev]
            const existingIndex = next.findIndex((item) => getContentKey(item) === incomingKey)
            if (existingIndex >= 0) {
              next[existingIndex] = incoming
            } else {
              next.unshift(incoming)
            }
            return next
          })

          setFlashItemKeys((prev) => (prev.includes(incomingKey) ? prev : [...prev, incomingKey]))
          if (event.action === 'created') {
            setPinnedNewItemKeys((prev) => [incomingKey, ...prev.filter((key) => key !== incomingKey)].slice(0, 40))
          }
        }

        const onCacheOrMetrics = () => {
          scheduleAdminRefresh()
        }

        socket.on('connect', onConnect)
        socket.on('content:event', onContentEvent)
        socket.on('cache:event', onCacheOrMetrics)
        socket.on('metrics:updated', onCacheOrMetrics)
      } catch {
        // Realtime is best-effort; UI remains functional with REST snapshots.
      }
    }

    void attachSocket()

    return () => {
      if (adminRefreshTimer) clearTimeout(adminRefreshTimer)
      socket?.disconnect()
    }
  }, [])

  useEffect(() => {
    const currentTtlKeys = adminOverview?.cache.expiringSoon.map((item) => item.key) ?? []
    const previousKeys = previousTtlKeysRef.current
    const newKeys = currentTtlKeys.filter((key) => !previousKeys.includes(key))
    if (newKeys.length > 0) {
      setFlashTtlKeys((prev) => Array.from(new Set([...prev, ...newKeys])))
    }
    previousTtlKeysRef.current = currentTtlKeys
  }, [adminOverview])

  const pageTitle = useMemo(() => {
    if (typeFilter === 'movie') return 'Film Arşivi'
    if (typeFilter === 'tvshow') return 'Dizi Arşivi'
    return 'Film ve Dizi Arşivi'
  }, [typeFilter])

  const allGenres = useMemo(() => {
    const genreSet = new Set<string>()
    for (const item of items) {
      for (const genre of item.genres) {
        genreSet.add(genre)
      }
    }
    return Array.from(genreSet).sort((a, b) => a.localeCompare(b, 'tr'))
  }, [items])

  const visibleItems = useMemo(() => {
    const searchText = search.trim().toLocaleLowerCase('tr')

    const filtered = items.filter((item) => {
      const matchesSearch =
        searchText.length === 0 ||
        item.title.toLocaleLowerCase('tr').includes(searchText) ||
        item.plot?.toLocaleLowerCase('tr').includes(searchText)

      const matchesGenre = !activeGenre || item.genres.includes(activeGenre)
      return matchesSearch && matchesGenre
    })

    return [...filtered].sort((a: ContentListItem, b: ContentListItem) => {
      const aPinnedIndex = pinnedNewItemKeys.indexOf(getContentKey(a))
      const bPinnedIndex = pinnedNewItemKeys.indexOf(getContentKey(b))
      const aPinned = aPinnedIndex >= 0
      const bPinned = bPinnedIndex >= 0
      if (aPinned || bPinned) {
        if (aPinned && bPinned) return aPinnedIndex - bPinnedIndex
        return aPinned ? -1 : 1
      }
      if (sortBy === 'year') {
        return (b.year ?? 0) - (a.year ?? 0)
      }
      return a.title.localeCompare(b.title, 'tr')
    })
  }, [items, search, sortBy, activeGenre, pinnedNewItemKeys])
  const selectedContent = useMemo(
    () => items.find((item) => getContentKey(item) === selectedContentKey) ?? null,
    [items, selectedContentKey]
  )

  const movieCount = items.filter((item) => item.type === 'movie').length
  const tvCount = items.filter((item) => item.type === 'tvshow').length
  const hasActiveFilters = typeFilter !== 'all' || search.trim().length > 0 || activeGenre !== null || sortBy !== 'title'
  const averageJobDurationSeconds = adminOverview ? Math.max(1, Math.round(adminOverview.jobs.averageDurationMs / 1000)) : 0
  const heroDescription =
    activeView === 'catalog'
      ? 'Filtrele, ara ve arşivi hızlıca tara. Film ve dizi keşfini tek akışta yönet.'
      : 'Operasyon görünümü: cache sağlığı, veri kalitesi ve scrape job durumlarını izle.'

  const openContentModal = (item: ContentListItem) => {
    setSelectedContentKey(getContentKey(item))
  }

  const closeContentModal = () => {
    setSelectedContentKey(null)
  }

  return (
    <Container size="xl" py="xl" className="catalog-page">
      <Stack gap="lg">
        <Paper className="catalog-hero" radius="xl" p="xl" withBorder>
          <Group justify="space-between" align="end" gap="md">
            <Stack gap={8}>
              <Text className="eyebrow">RateBubble koleksiyonu</Text>
              <Title order={1}>{pageTitle}</Title>
              <Text c="dimmed" maw={620}>
                {heroDescription}
              </Text>
            </Stack>
            <Group gap="sm" className="stats-wrap">
              <Paper className="stat-pill" radius="xl" p="sm" withBorder>
                <Text size="xs" c="dimmed">
                  Toplam
                </Text>
                <Text fw={700} size="lg">
                  {items.length}
                </Text>
              </Paper>
              <Paper className="stat-pill" radius="xl" p="sm" withBorder>
                <Text size="xs" c="dimmed">
                  Film
                </Text>
                <Text fw={700} size="lg">
                  {movieCount}
                </Text>
              </Paper>
              <Paper className="stat-pill" radius="xl" p="sm" withBorder>
                <Text size="xs" c="dimmed">
                  Dizi
                </Text>
                <Text fw={700} size="lg">
                  {tvCount}
                </Text>
              </Paper>
            </Group>
          </Group>
        </Paper>

        <Paper radius="lg" p="xs" withBorder className="view-nav">
          <Group gap={8} wrap="nowrap">
            <Button
              className={`nav-pill ${activeView === 'catalog' ? 'is-active' : 'is-inactive'}`}
              variant={activeView === 'catalog' ? 'filled' : 'subtle'}
              leftSection={<IconChartBar size={16} />}
              onClick={() => setActiveView('catalog')}
            >
              Icerik Katalogu
            </Button>
            <Button
              className={`nav-pill ${activeView === 'admin' ? 'is-active' : 'is-inactive'}`}
              variant={activeView === 'admin' ? 'filled' : 'subtle'}
              leftSection={<IconLayoutDashboard size={16} />}
              onClick={() => setActiveView('admin')}
            >
              Yonetici Dashboard
            </Button>
          </Group>
        </Paper>

        {activeView === 'admin' && (
        <Paper radius="lg" p="lg" withBorder className="admin-panel">
          <Stack gap="md">
            <Group justify="space-between" wrap="wrap" gap="sm">
              <div>
                <Title order={2}>Yonetici Dashboard</Title>
                <Text size="sm" c="dimmed">
                  Redis, veritabani ve scrape operasyon durumu.
                </Text>
              </div>
              <Group gap="xs">
                <Badge variant="light" color="gray">
                  Ortam: {adminOverview?.environment ?? '-'}
                </Badge>
                <Button
                  size="compact-sm"
                  variant="outline"
                  loading={adminRefreshing}
                  onClick={() => void handleAdminRefresh()}
                >
                  Yenile
                </Button>
                <Button
                  size="compact-sm"
                  variant="light"
                  loading={adminActionPending === 'warmup-cache'}
                  onClick={() => void runAdminAction('warmup-cache', '/api/admin/cache/warmup')}
                >
                  DB to Redis
                </Button>
                <Button
                  size="compact-sm"
                  variant="light"
                  loading={adminActionPending === 'clear-cache'}
                  onClick={() => void runAdminAction('clear-cache', '/api/admin/cache/clear')}
                >
                  Cache temizle
                </Button>
                <Button
                  size="compact-sm"
                  variant="light"
                  loading={adminActionPending === 'retry-failed'}
                  onClick={() =>
                    void runAdminAction('retry-failed', '/api/admin/jobs/retry-failed', {
                      limit: 10,
                    })
                  }
                >
                  Failed retry
                </Button>
                <Button
                  size="compact-sm"
                  variant="light"
                  loading={adminActionPending === 'refresh-stale'}
                  onClick={() =>
                    void runAdminAction('refresh-stale', '/api/admin/content/refresh-stale', {
                      days: 30,
                      limit: 20,
                    })
                  }
                >
                  Stale refresh
                </Button>
              </Group>
            </Group>

            {adminError && (
              <Alert icon={<IconAlertCircle size={16} />} color="orange" title="Dashboard Hatasi">
                {adminError}
              </Alert>
            )}

            {adminLoading ? (
              <Grid>
                {Array.from({ length: 4 }).map((_, idx) => (
                  <Grid.Col key={idx} span={{ base: 12, sm: 6, md: 3 }}>
                    <Paper withBorder radius="md" p="md" className="admin-card">
                      <Skeleton height={14} width="55%" />
                      <Skeleton height={28} width="35%" mt="sm" />
                    </Paper>
                  </Grid.Col>
                ))}
              </Grid>
            ) : (
              adminOverview && (
                <>
                  <Grid>
                    <Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
                      <Paper withBorder radius="md" p="md" className="admin-card">
                        <Text size="xs" c="dimmed">
                          Redis Key Sayisi
                        </Text>
                        <Title order={3}>{adminOverview.cache.keyCount}</Title>
                        <Text size="xs" c="dimmed">
                          Toplam {Math.round(adminOverview.cache.totalBytes / 1024)} KB
                        </Text>
                        <Text size="xs" c="dimmed">
                          RAM {formatBytes(adminOverview.cache.redisMemory.usedBytes)}/
                          {adminOverview.cache.redisMemory.maxBytes
                            ? formatBytes(adminOverview.cache.redisMemory.maxBytes)
                            : 'Limitsiz'}
                        </Text>
                      </Paper>
                    </Grid.Col>
                    <Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
                      <Paper withBorder radius="md" p="md" className="admin-card">
                        <Text size="xs" c="dimmed">
                          TTL Dagilimi (5dk alti)
                        </Text>
                        <Title order={3}>{adminOverview.cache.ttlDistribution.lessThan5Min}</Title>
                        <Text size="xs" c="dimmed">
                          Varsayilan TTL: {adminOverview.cache.configuredTtlSeconds}s
                        </Text>
                      </Paper>
                    </Grid.Col>
                    <Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
                      <Paper withBorder radius="md" p="md" className="admin-card">
                        <Text size="xs" c="dimmed">
                          Icerik Toplami
                        </Text>
                        <Title order={3}>{adminOverview.content.total}</Title>
                        <Text size="xs" c="dimmed">
                          Film {adminOverview.content.byType.movie} / Dizi {adminOverview.content.byType.tvshow}
                        </Text>
                      </Paper>
                    </Grid.Col>
                    <Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
                      <Paper withBorder radius="md" p="md" className="admin-card">
                        <Text size="xs" c="dimmed">
                          Cache Hit Orani
                        </Text>
                        <Title order={3}>{Math.round(adminOverview.requestMetrics.cacheHitRate * 100)}%</Title>
                        <Text size="xs" c="dimmed">
                          Hit {adminOverview.requestMetrics.cacheHits} / Miss {adminOverview.requestMetrics.cacheMisses}
                        </Text>
                      </Paper>
                    </Grid.Col>
                    <Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
                      <Paper withBorder radius="md" p="md" className="admin-card">
                        <Text size="xs" c="dimmed">
                          Job Durumu
                        </Text>
                        <Title order={3}>{adminOverview.jobs.counts.processing}</Title>
                        <Text size="xs" c="dimmed">
                          Aktif, ort. {averageJobDurationSeconds}s
                        </Text>
                      </Paper>
                    </Grid.Col>
                  </Grid>

                  <Grid>
                    <Grid.Col span={{ base: 12, md: 6 }}>
                      <Paper withBorder radius="md" p="md" className="admin-card">
                        <Text fw={600}>Cache TTL Dagilimi</Text>
                        <Group gap="xs" mt="xs">
                          <Badge variant="light">TTL yok/suresi gecmis: {adminOverview.cache.ttlDistribution.expiredOrNoTtl}</Badge>
                          <Badge variant="light">0-5dk: {adminOverview.cache.ttlDistribution.lessThan5Min}</Badge>
                          <Badge variant="light">5-30dk: {adminOverview.cache.ttlDistribution.min5To30}</Badge>
                          <Badge variant="light">30dk+: {adminOverview.cache.ttlDistribution.min30Plus}</Badge>
                        </Group>
                        <Text size="xs" c="dimmed" mt="sm">
                          {adminOverview.cache.sampled
                            ? `Yuksek hacim nedeniyle ilk ${adminOverview.cache.analyzedKeyLimit} key analiz edildi.`
                            : 'Tum cache keyleri analiz edildi.'}
                        </Text>
                        <Stack gap={6} mt="md">
                          <Text size="sm" fw={600}>
                            En yakin sure dolacak keyler
                          </Text>
                          {adminOverview.cache.expiringSoon.length === 0 ? (
                            <Text size="sm" c="dimmed">
                              Gosterilecek key bulunamadi.
                            </Text>
                          ) : (
                            adminOverview.cache.expiringSoon.map((item) => (
                              <Group
                                key={item.key}
                                justify="space-between"
                                className={`list-row ${flashTtlKeys.includes(item.key) ? 'live-ttl-flash' : ''}`}
                              >
                                <Text
                                  size="sm"
                                  className="cache-key-text"
                                  title={item.mediaTitle ? `${item.key} | ${item.mediaTitle}` : item.key}
                                >
                                  {item.mediaTitle ? `${item.key} | ${item.mediaTitle}` : item.key}
                                </Text>
                                <Badge variant="outline" title={`${item.ttlSeconds}s`}>
                                  {formatTtl(item.ttlSeconds)}
                                </Badge>
                              </Group>
                            ))
                          )}
                        </Stack>
                      </Paper>
                    </Grid.Col>

                    <Grid.Col span={{ base: 12, md: 6 }}>
                      <Stack gap="md">
                        <Paper withBorder radius="md" p="md" className="admin-card">
                          <Text fw={600}>Veritabani Ozeti</Text>
                          <Group gap="xs" mt="xs">
                            <Badge variant="light">24s eklenen: {adminOverview.content.addedLast24h}</Badge>
                            <Badge variant="light">7g eklenen: {adminOverview.content.addedLast7d}</Badge>
                            <Badge color="orange" variant="light">
                              Plot eksik: {adminOverview.content.metadataGaps.missingPlot}
                            </Badge>
                            <Badge color="yellow" variant="light">
                              Yas siniri eksik: {adminOverview.content.metadataGaps.missingAgeRating}
                            </Badge>
                            <Badge color="grape" variant="light">
                              Backdrop eksik: {adminOverview.content.metadataGaps.missingBackdrop}
                            </Badge>
                          </Group>
                          <Stack gap={6} mt="md">
                            <Text size="sm" fw={600}>
                              En Populer Turler
                            </Text>
                            {adminOverview.content.topGenres.map((genre) => (
                              <Group key={genre.name} justify="space-between" className="list-row">
                                <Text size="sm">{genre.name}</Text>
                                <Badge variant="dot">{genre.count}</Badge>
                              </Group>
                            ))}
                          </Stack>
                        </Paper>

                        <Paper withBorder radius="md" p="md" className="admin-card">
                          <Text fw={600}>Job ve Hata Ozeti</Text>
                          <Group gap="xs" mt="xs">
                            <Badge variant="light">Pending: {adminOverview.jobs.counts.pending}</Badge>
                            <Badge variant="light">Processing: {adminOverview.jobs.counts.processing}</Badge>
                            <Badge color="green" variant="light">
                              Completed: {adminOverview.jobs.counts.completed}
                            </Badge>
                            <Badge color="red" variant="light">
                              Failed: {adminOverview.jobs.counts.failed}
                            </Badge>
                          </Group>
                          <Group gap="xs" mt="sm">
                            <Badge variant="light">Kaynak Cache: {adminOverview.requestMetrics.sourceCounts.cache}</Badge>
                            <Badge variant="light">Kaynak DB: {adminOverview.requestMetrics.sourceCounts.database}</Badge>
                            <Badge variant="light">Kaynak Netflix: {adminOverview.requestMetrics.sourceCounts.netflix}</Badge>
                          </Group>
                          <Stack gap={6} mt="md">
                            <Text size="sm" fw={600}>
                              Son Basarisiz Isler
                            </Text>
                            {adminOverview.jobs.failedRecent.length === 0 ? (
                              <Text size="sm" c="dimmed">
                                Son donemde hata kaydi yok.
                              </Text>
                            ) : (
                              adminOverview.jobs.failedRecent.map((job) => (
                                <div key={job.id} className="list-row">
                                  <Text size="sm" fw={500} lineClamp={1}>
                                    {job.url}
                                  </Text>
                                  <Text size="xs" c="red.3" lineClamp={1}>
                                    {job.error}
                                  </Text>
                                </div>
                              ))
                            )}
                          </Stack>
                        </Paper>
                      </Stack>
                    </Grid.Col>
                  </Grid>
                </>
              )
            )}
          </Stack>
        </Paper>
        )}

        {activeView === 'catalog' && (
          <Stack gap="md" px={{ base: 'xs', sm: 'lg' }} className="catalog-view-shell">
            <Paper radius="lg" p="md" className="toolbar" withBorder>
              <Stack gap="sm">
                <Group justify="space-between" gap="sm" wrap="wrap">
                  <SegmentedControl
                    value={typeFilter}
                    onChange={(value) => {
                      setTypeFilter(value as 'all' | ContentType)
                      setActiveGenre(null)
                    }}
                    data={[
                      { label: 'Tümü', value: 'all' },
                      { label: 'Filmler', value: 'movie' },
                      { label: 'Diziler', value: 'tvshow' },
                    ]}
                  />

                  <Group gap="sm" wrap="wrap">
                    <TextInput
                      placeholder="Başlık veya açıklama ara"
                      leftSection={<IconSearch size={16} />}
                      value={search}
                      onChange={(event) => setSearch(event.currentTarget.value)}
                      className="search-input"
                    />
                    <SegmentedControl
                      value={sortBy}
                      onChange={(value) => setSortBy(value as SortBy)}
                      data={[
                        {
                          label: (
                            <Group gap={6} wrap="nowrap">
                              <IconSortAscendingLetters size={14} />
                              <span>Başlık</span>
                            </Group>
                          ),
                          value: 'title',
                        },
                        { label: 'Yıl', value: 'year' },
                      ]}
                    />
                  </Group>
                </Group>

                <Group gap="xs" wrap="wrap" justify="space-between">
                  <Group gap="xs" wrap="wrap">
                    <Button
                      variant={activeGenre ? 'light' : 'filled'}
                      size="compact-sm"
                      radius="xl"
                      className="genre-chip"
                      onClick={() => setActiveGenre(null)}
                      aria-pressed={!activeGenre}
                    >
                      Tüm Türler
                    </Button>
                    {allGenres.slice(0, 12).map((genre) => (
                      <Button
                        key={genre}
                        variant={activeGenre === genre ? 'filled' : 'light'}
                        size="compact-sm"
                        radius="xl"
                        className="genre-chip"
                        onClick={() => setActiveGenre(activeGenre === genre ? null : genre)}
                        aria-pressed={activeGenre === genre}
                      >
                        {genre}
                      </Button>
                    ))}
                  </Group>
                  {hasActiveFilters && (
                    <Button
                      variant="outline"
                      size="compact-sm"
                      radius="xl"
                      className="genre-chip"
                      leftSection={<IconX size={14} />}
                      onClick={() => {
                        setTypeFilter('all')
                        setSearch('')
                        setSortBy('title')
                        setActiveGenre(null)
                      }}
                    >
                      Filtreleri temizle
                    </Button>
                  )}
                </Group>
              </Stack>
            </Paper>

            {error && (
              <Alert icon={<IconAlertCircle size={16} />} color="red" title="Hata">
                {error}
              </Alert>
            )}

            {loading ? (
              <Grid>
                {Array.from({ length: 9 }).map((_, idx) => (
                  <Grid.Col key={idx} span={{ base: 12, sm: 6, md: 4 }}>
                    <Card withBorder radius="lg" p="md" className="catalog-card">
                      <Skeleton height={180} radius="md" />
                      <Stack mt="md" gap="xs">
                        <Skeleton height={16} width="75%" />
                        <Skeleton height={12} width="45%" />
                        <Skeleton height={12} width="90%" />
                        <Skeleton height={12} width="70%" />
                      </Stack>
                    </Card>
                  </Grid.Col>
                ))}
              </Grid>
            ) : (
              <Grid>
                {visibleItems.map((item, index) => {
                  const itemKey = getContentKey(item)
                  const isLive = flashItemKeys.includes(itemKey)
                  return (
                  <Grid.Col key={itemKey} span={{ base: 12, sm: 6, md: 4 }}>
                    <Card
                      shadow="md"
                      radius="lg"
                      padding="md"
                      withBorder
                      tabIndex={0}
                      role="button"
                      aria-label={`${item.title} detaylarini ac`}
                      aria-haspopup="dialog"
                      className={`catalog-card reveal ${isLive ? 'live-fade-in' : ''}`}
                      style={{ animationDelay: `${Math.min(index * 45, 420)}ms` }}
                      onClick={() => openContentModal(item)}
                      onKeyDown={(event) => {
                        if (event.key === 'Enter' || event.key === ' ') {
                          event.preventDefault()
                          openContentModal(item)
                        }
                      }}
                    >
                      <Card.Section className="media-wrap">
                        {item.backdrop ? (
                          <BackdropImage src={item.backdrop} alt={item.title} />
                        ) : (
                          <Group h={190} justify="center" className="media-fallback">
                            {item.type === 'movie' ? <IconMovie size={54} /> : <IconDeviceTv size={54} />}
                          </Group>
                        )}
                        <div className="media-overlay" />
                      </Card.Section>

                      <Stack gap="xs" mt="md" pb="lg" className="card-content">
                        <Group justify="space-between" align="start" gap="xs">
                          <Text fw={700} lineClamp={2} className="card-title">
                            {item.title}
                          </Text>
                          <Badge color={item.type === 'movie' ? 'red' : 'blue'}>
                            {item.type === 'movie' ? 'Film' : 'Dizi'}
                          </Badge>
                        </Group>

                        <Group gap="xs">
                          {item.year && <Badge variant="light">{item.year}</Badge>}
                          {item.ageRating && <Badge variant="outline">{item.ageRating}</Badge>}
                          {item.currentSeason && item.type === 'tvshow' && (
                            <Badge variant="light" color="grape">
                              S{item.currentSeason}
                            </Badge>
                          )}
                        </Group>

                        <Text size="sm" c="dimmed" lineClamp={3}>
                          {item.plot || 'Açıklama bulunamadı.'}
                        </Text>

                        <Group gap={6}>
                          {item.genres.slice(0, 3).map((genre) => (
                            <Badge key={genre} size="sm" variant="dot">
                              {genre}
                            </Badge>
                          ))}
                        </Group>
                      </Stack>

                      <img src="/netflix.png" alt="Netflix" className="brand-stamp" />
                    </Card>
                  </Grid.Col>
                  )
                })}
              </Grid>
            )}

            {!loading && !error && visibleItems.length === 0 && (
              <Paper radius="lg" p="xl" ta="center" withBorder className="empty-state">
                <Stack gap="sm" align="center">
                  <Loader size="sm" type="dots" color="red" />
                  <Title order={3}>Sonuç bulunamadı</Title>
                  <Text c="dimmed">Filtreleri temizleyip farklı bir anahtar kelime deneyebilirsin.</Text>
                </Stack>
              </Paper>
            )}
          </Stack>
        )}
      </Stack>
      <Modal
        opened={Boolean(selectedContent)}
        onClose={closeContentModal}
        centered
        size="xl"
        radius="lg"
        lockScroll={false}
        transitionProps={{ duration: 90, transition: 'fade' }}
        classNames={{
          content: 'detail-modal-content',
          header: 'detail-modal-header',
          body: 'detail-modal-body',
        }}
        overlayProps={{ blur: 4, opacity: 0.8 }}
        title={null}
      >
        {selectedContent && (
          <Stack gap="md">
            <div className="detail-media-wrap">
              {selectedContent.backdrop ? (
                <Image src={selectedContent.backdrop} alt={selectedContent.title} h={230} />
              ) : (
                <Group h={230} justify="center" className="media-fallback">
                  {selectedContent.type === 'movie' ? <IconMovie size={58} /> : <IconDeviceTv size={58} />}
                </Group>
              )}
              <div className="detail-media-overlay" />
              <div className="detail-title-group">
                <Badge color={selectedContent.type === 'movie' ? 'red' : 'blue'}>
                  {selectedContent.type === 'movie' ? 'Film' : 'Dizi'}
                </Badge>
                <Title order={2} className="detail-title">
                  {selectedContent.title}
                </Title>
              </div>
            </div>

            <Group gap="xs">
              {selectedContent.year && <Badge variant="light">{selectedContent.year}</Badge>}
              {selectedContent.ageRating && <Badge variant="outline">{selectedContent.ageRating}</Badge>}
              {selectedContent.currentSeason && selectedContent.type === 'tvshow' && (
                <Badge variant="light" color="grape">
                  Sezon {selectedContent.currentSeason}
                </Badge>
              )}
            </Group>

            <Text c="dimmed" size="sm" className="detail-plot">
              {selectedContent.plot || 'Açıklama bulunamadı.'}
            </Text>

            <Divider color="rgba(255,255,255,0.14)" />

            <Stack gap={8}>
              <Text fw={600} size="sm">
                Türler
              </Text>
              <Group gap={6}>
                {selectedContent.genres.length > 0 ? (
                  selectedContent.genres.map((genre) => (
                    <Badge key={genre} size="sm" variant="dot">
                      {genre}
                    </Badge>
                  ))
                ) : (
                  <Text size="sm" c="dimmed">
                    Tür bilgisi yok.
                  </Text>
                )}
              </Group>
            </Stack>

            <Stack gap={8}>
              <Text fw={600} size="sm">
                Oyuncular
              </Text>
              <Group gap={6}>
                {selectedContent.cast && selectedContent.cast.length > 0 ? (
                  selectedContent.cast.slice(0, 14).map((castName) => (
                    <Badge key={castName} size="sm" variant="light" color="gray">
                      {castName}
                    </Badge>
                  ))
                ) : (
                  <Text size="sm" c="dimmed">
                    Oyuncu bilgisi bulunamadı.
                  </Text>
                )}
              </Group>
            </Stack>
            <img src="/netflix.png" alt="Netflix" className="detail-brand-stamp" />
          </Stack>
        )}
      </Modal>
      {adminActionMessage && (
        <div className="admin-toast" role="status" aria-live="polite">
          {adminActionMessage}
        </div>
      )}
    </Container>
  )
}
