import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { useState, useEffect, useRef } from 'react'
import { useBreadcrumb } from '../hooks/useBreadcrumb'
import { breadcrumbConfig } from '../config/breadcrumbConfig'
import {
  Calendar, Tv, Mic, Radio, CheckCircle,
  Clock, Eye, EyeOff, Loader2, ChevronRight, Film, Play,
  Clapperboard, Megaphone, PenTool, Sparkles, User, RefreshCcw, MonitorPlay, Bell, Filter
} from 'lucide-react'
import { api } from '../lib/api'
import { notificationManager } from '../lib/notificationManager'
import { format, parseISO, formatDistanceToNow, isBefore } from 'date-fns'
import AppearanceDetailModal from '../components/AppearanceDetailModal'
import { FilterBar } from '../components/FilterPopover'

// Sanitize HTML to prevent XSS - allow only safe formatting tags
function sanitizeHtml(html: string): string {
  if (!html) return ''
  const div = document.createElement('div')
  div.textContent = ''
  // Parse HTML but only allow safe tags
  const temp = document.createElement('div')
  temp.innerHTML = html
  const allowedTags = new Set(['B', 'I', 'EM', 'STRONG', 'BR', 'P', 'SPAN', 'A'])
  function walkAndSanitize(node: Node, parent: HTMLElement) {
    if (node.nodeType === Node.TEXT_NODE) {
      parent.appendChild(document.createTextNode(node.textContent || ''))
    } else if (node.nodeType === Node.ELEMENT_NODE) {
      const el = node as HTMLElement
      if (allowedTags.has(el.tagName)) {
        const safe = document.createElement(el.tagName)
        // Only copy safe attributes for anchor tags
        if (el.tagName === 'A') {
          const href = el.getAttribute('href')
          if (href && (href.startsWith('http://') || href.startsWith('https://'))) {
            safe.setAttribute('href', href)
            safe.setAttribute('target', '_blank')
            safe.setAttribute('rel', 'noopener noreferrer')
          }
        }
        el.childNodes.forEach(child => walkAndSanitize(child, safe))
        parent.appendChild(safe)
      } else {
        // For disallowed tags, process children as text
        el.childNodes.forEach(child => walkAndSanitize(child, parent))
      }
    }
  }
  temp.childNodes.forEach(child => walkAndSanitize(child, div))
  return div.innerHTML
}

interface Appearance {
  id: number
  celebrity_id: number
  celebrity_name: string
  appearance_type: 'TV' | 'Movie' | 'Podcast' | 'Radio'
  show_name: string
  episode_title: string | null
  network: string | null
  appearance_date: string
  url: string | null
  audio_url: string | null
  watch_url: string | null
  description: string | null
  tmdb_show_id: number | null
  season_number: number | null
  episode_number: number | null
  status: string
  poster_url: string | null
  episode_count: number
  credit_type: 'acting' | 'host' | 'directing' | 'producing' | 'writing' | 'creator' | 'guest' | null
  character_name: string | null
  job_title: string | null
  plex_rating_key: string | null
  plex_watch_url: string | null
  all_credit_types?: string[]
}

// Credit type configuration for badges
const creditTypeConfig = {
  acting: { label: 'Acting', color: 'bg-blue-500/10 text-blue-600 dark:text-blue-400', icon: User },
  directing: { label: 'Directing', color: 'bg-amber-500/10 text-amber-600 dark:text-amber-400', icon: Clapperboard },
  producing: { label: 'Producing', color: 'bg-green-500/10 text-green-600 dark:text-green-400', icon: Megaphone },
  writing: { label: 'Writing', color: 'bg-purple-500/10 text-purple-600 dark:text-purple-400', icon: PenTool },
  creator: { label: 'Creator', color: 'bg-pink-500/10 text-pink-600 dark:text-pink-400', icon: Sparkles },
  guest: { label: 'Guest', color: 'bg-cyan-500/10 text-cyan-600 dark:text-cyan-400', icon: User },
  host: { label: 'Host', color: 'bg-orange-500/10 text-orange-600 dark:text-orange-400', icon: Mic },
}

interface SyncProgress {
  is_running: boolean
  current_celebrity: string | null
  celebrities_processed: number
  total_celebrities: number
  new_appearances: number
  started_at: string | null
  last_update: string | null
  phase: 'fetching_movies' | 'fetching_tv' | 'fetching_podcasts' | 'fetching_podcasts_taddy' | 'fetching' | 'saving' | 'complete' | null
  current_show?: string | null
  shows_processed?: number
  total_shows?: number
  current_podcast?: string | null
  podcasts_processed?: number
  total_podcasts?: number
}

export default function Appearances() {
  useBreadcrumb(breadcrumbConfig['/appearances'])
  const queryClient = useQueryClient()
  const [activeTab, setActiveTab] = useState<'upcoming' | 'aired' | 'watched' | 'all' | 'notifications'>('upcoming')
  const [searchQuery, setSearchQuery] = useState('')
  const [selectedCelebrity, setSelectedCelebrity] = useState<string>('all')
  const [selectedType, setSelectedType] = useState<string>('all')
  const [selectedCreditType, setSelectedCreditType] = useState<string>('all')
  const [plexOnly, setPlexOnly] = useState<boolean>(false)
  const [selectedAppearance, setSelectedAppearance] = useState<Appearance | null>(null)
  const [dateFilter, setDateFilter] = useState<'all' | '7days' | '30days' | 'custom'>('all')
  const [customStartDate, setCustomStartDate] = useState('')
  const [customEndDate, setCustomEndDate] = useState('')
  const [syncProgress, setSyncProgress] = useState<SyncProgress>({
    is_running: false,
    current_celebrity: null,
    celebrities_processed: 0,
    total_celebrities: 0,
    new_appearances: 0,
    started_at: null,
    last_update: null,
    phase: null,
    current_show: null,
    shows_processed: 0,
    total_shows: 0,
    current_podcast: null,
    podcasts_processed: 0,
    total_podcasts: 0,
  })

  // Fetch appearances based on active tab (use specialized endpoints for better performance)
  const { data: appearances, isLoading, refetch } = useQuery({
    queryKey: ['all-appearances', activeTab, selectedType, selectedCelebrity, selectedCreditType, searchQuery, dateFilter, customStartDate, customEndDate, plexOnly],
    queryFn: async () => {
      // Use specialized endpoints for upcoming/aired tabs when no filters are active
      const hasFilters = selectedType !== 'all' || selectedCelebrity !== 'all' || selectedCreditType !== 'all' || searchQuery || dateFilter !== 'all' || plexOnly

      if (!hasFilters) {
        if (activeTab === 'upcoming') {
          return api.getUpcomingAppearances({ limit: 100, days_ahead: 1825 }) // 5 years to catch all upcoming
        } else if (activeTab === 'aired') {
          return api.getAiredAppearances({ limit: 100, days_back: 36500 }) // 100 years - show all history
        }
      }

      // Fall back to getAllAppearances for filtered queries or other tabs
      return api.getAllAppearances({
        status: activeTab,
        appearance_type: selectedType,
        celebrity_name: selectedCelebrity,
        credit_type: selectedCreditType,
        search: searchQuery,
        date_filter: dateFilter,
        start_date: customStartDate,
        end_date: customEndDate,
        plex_only: plexOnly,
      })
    },
    refetchInterval: 60000, // Refresh every minute
    refetchOnMount: true, // Always refetch when component mounts
    refetchOnWindowFocus: true, // Refetch when window regains focus (mobile return)
    staleTime: 0, // Data is always stale, ensuring fresh fetch
  })

  // Mark watched mutation
  const markWatchedMutation = useMutation({
    mutationFn: (appearanceId: number) => api.updateAppearanceStatus(appearanceId, 'watched'),
    onSuccess: () => {
      notificationManager.success('Success', 'Marked as watched')
      refetch()
    },
    onError: (err: unknown) => {
      notificationManager.apiError('Error', err)
    },
  })

  // Mark ignored mutation
  const markIgnoredMutation = useMutation({
    mutationFn: (appearanceId: number) => api.updateAppearanceStatus(appearanceId, 'ignored'),
    onSuccess: () => {
      notificationManager.success('Success', 'Marked as ignored')
      refetch()
    },
    onError: (err: unknown) => {
      notificationManager.apiError('Error', err)
    },
  })

  // Sync mutation
  const syncMutation = useMutation({
    mutationFn: () => api.syncAppearances(),
    onSuccess: () => {
      setSyncProgress(prev => ({ ...prev, is_running: true }))
    },
    onError: (err: unknown) => {
      notificationManager.syncError('Appearances', err)
    },
  })

  // Plex match mutation with proper cleanup
  const [matchingPlex, setMatchingPlex] = useState(false)
  const plexMatchIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null)
  const plexMatchTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)

  // Cleanup Plex match polling on unmount
  useEffect(() => {
    return () => {
      if (plexMatchIntervalRef.current) clearInterval(plexMatchIntervalRef.current)
      if (plexMatchTimeoutRef.current) clearTimeout(plexMatchTimeoutRef.current)
    }
  }, [])

  const matchPlexMutation = useMutation({
    mutationFn: () => api.matchAppearancesToPlex(),
    onSuccess: () => {
      setMatchingPlex(true)
      // Poll for completion with refs for cleanup
      plexMatchIntervalRef.current = setInterval(async () => {
        await refetch()
        queryClient.invalidateQueries({ queryKey: ['plex-stats'] })
      }, 3000)
      plexMatchTimeoutRef.current = setTimeout(() => {
        if (plexMatchIntervalRef.current) clearInterval(plexMatchIntervalRef.current)
        setMatchingPlex(false)
        refetch()
        queryClient.invalidateQueries({ queryKey: ['plex-stats'] })
      }, 120000)
    },
    onError: (err: unknown) => {
      setMatchingPlex(false)
      notificationManager.apiError('Plex Match Failed', err)
    },
  })

  // Check sync status on mount and poll when running
  useEffect(() => {
    const checkSyncStatus = async () => {
      try {
        const status = await api.getAppearanceSyncStatus()
        setSyncProgress(status)
      } catch (error) {
        console.error('Error checking sync status:', error)
      }
    }
    checkSyncStatus()
  }, [])

  // Refs for values used inside polling interval (avoids unstable deps causing re-renders)
  const syncProgressRef = useRef(syncProgress)
  syncProgressRef.current = syncProgress
  const matchingPlexRef = useRef(matchingPlex)
  matchingPlexRef.current = matchingPlex
  const matchPlexMutationRef = useRef(matchPlexMutation)
  matchPlexMutationRef.current = matchPlexMutation

  // Poll for sync status when running
  useEffect(() => {
    if (!syncProgress.is_running) return

    const pollInterval = setInterval(async () => {
      try {
        const status = await api.getAppearanceSyncStatus()
        setSyncProgress(status)

        // Refresh data and trigger Plex sync when sync completes
        if (!status.is_running && syncProgressRef.current.is_running) {
          queryClient.invalidateQueries({ queryKey: ['all-appearances'] })
          queryClient.invalidateQueries({ queryKey: ['all-appearances-unfiltered'] })
          // Automatically run Plex sync after appearances sync completes
          if (!matchingPlexRef.current && !matchPlexMutationRef.current.isPending) {
            matchPlexMutationRef.current.mutate()
          }
        }
      } catch (error) {
        console.error('Error polling sync status:', error)
      }
    }, 2000)

    return () => clearInterval(pollInterval)
  }, [syncProgress.is_running, queryClient])

  // Fetch all unfiltered data for counts and dropdown options
  const { data: allAppearances } = useQuery({
    queryKey: ['all-appearances-unfiltered'],
    queryFn: () => api.getAllAppearances(),
    refetchInterval: 60000,
  })

  // Fetch Plex matching stats
  const { data: plexStats } = useQuery({
    queryKey: ['plex-stats'],
    queryFn: () => api.getPlexStats(),
    refetchInterval: 30000, // Refresh every 30 seconds
  })

  // Fetch appearance notifications
  const { data: notificationsData, isLoading: notificationsLoading } = useQuery({
    queryKey: ['appearance-notifications'],
    queryFn: () => api.getAppearanceNotifications({ limit: 100 }),
    refetchInterval: 60000, // Refresh every minute
    enabled: activeTab === 'notifications', // Only fetch when on notifications tab
  })

  // Fetch notification stats
  const { data: notificationStats } = useQuery({
    queryKey: ['appearance-notification-stats'],
    queryFn: () => api.getAppearanceNotificationStats(),
    refetchInterval: 60000,
  })

  // Server-side filtering - no client-side filtering needed
  const filteredAppearances = appearances || []

  // Get unique celebrities for filter (from all data for dropdown)
  const uniqueCelebrities = [...new Set(allAppearances?.map(a => a.celebrity_name) || [])].sort()

  // Type config
  const typeConfig = {
    TV: { icon: Tv, color: 'bg-gradient-to-br from-purple-600 to-indigo-600', label: 'TV' },
    Movie: { icon: Film, color: 'bg-gradient-to-br from-red-600 to-pink-600', label: 'Movie' },
    Podcast: { icon: Mic, color: 'bg-gradient-to-br from-green-600 to-emerald-600', label: 'Podcast' },
    Radio: { icon: Radio, color: 'bg-gradient-to-br from-orange-600 to-amber-600', label: 'Radio' },
  }

  // Tab counts (from all unfiltered data)
  const upcomingCount = allAppearances?.filter(a => a.status === 'upcoming').length || 0
  const airedCount = allAppearances?.filter(a => a.status === 'aired').length || 0
  const watchedCount = allAppearances?.filter(a => a.status === 'watched').length || 0

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
        <div>
          <h1 className="text-2xl sm:text-3xl font-bold flex items-center gap-2 sm:gap-3">
            <Calendar className="w-6 h-6 sm:w-8 sm:h-8 text-cyan-500" />
            Celebrity Appearances
          </h1>
          <p className="text-sm sm:text-base text-slate-600 dark:text-slate-400 mt-1">
            Track TV shows, podcasts, and radio appearances
          </p>
        </div>
        <div className="flex items-center gap-2">
          <button
            onClick={() => matchPlexMutation.mutate()}
            disabled={matchPlexMutation.isPending || matchingPlex}
            className="flex-1 sm:flex-initial px-3 sm:px-4 py-2.5 bg-gradient-to-r from-amber-600 to-orange-600 text-white rounded-lg font-medium text-sm flex items-center justify-center gap-2 hover:from-amber-700 hover:to-orange-700 disabled:opacity-50 disabled:cursor-not-allowed transition-all min-h-[44px]"
            title="Match appearances to Plex library"
          >
            <MonitorPlay className={`w-4 h-4 ${matchingPlex ? 'animate-pulse' : ''}`} />
            <span className="hidden sm:inline">{matchingPlex ? 'Matching...' : 'Match Plex'}</span>
            <span className="sm:hidden">{matchingPlex ? '...' : 'Plex'}</span>
          </button>
          <button
            onClick={() => syncMutation.mutate()}
            disabled={syncMutation.isPending || syncProgress.is_running}
            className="flex-1 sm:flex-initial px-3 sm:px-4 py-2.5 bg-gradient-to-r from-cyan-600 to-blue-600 text-white rounded-lg font-medium text-sm flex items-center justify-center gap-2 hover:from-cyan-700 hover:to-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-all min-h-[44px]"
          >
            <RefreshCcw className={`w-4 h-4 ${syncMutation.isPending || syncProgress.is_running ? 'animate-spin' : ''}`} />
            {syncProgress.is_running ? 'Syncing...' : 'Sync'}
          </button>
        </div>
      </div>

      {/* Tabs */}
      <div className="border-b border-slate-200 dark:border-slate-700">
        <div className="flex space-x-1 overflow-x-auto">
          <button
            onClick={() => setActiveTab('upcoming')}
            className={`flex items-center gap-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
              activeTab === 'upcoming'
                ? 'border-cyan-500 text-cyan-600 dark:text-cyan-400'
                : 'border-transparent text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-100'
            }`}
          >
            <Clock className="w-4 h-4" />
            Upcoming
            {upcomingCount > 0 && (
              <span className={`px-2 py-0.5 rounded-full text-xs ${
                activeTab === 'upcoming'
                  ? 'bg-cyan-100 dark:bg-cyan-900/30 text-cyan-700 dark:text-cyan-300'
                  : 'bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400'
              }`}>
                {upcomingCount}
              </span>
            )}
          </button>

          <button
            onClick={() => setActiveTab('aired')}
            className={`flex items-center gap-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
              activeTab === 'aired'
                ? 'border-cyan-500 text-cyan-600 dark:text-cyan-400'
                : 'border-transparent text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-100'
            }`}
          >
            <Tv className="w-4 h-4" />
            Aired
            {airedCount > 0 && (
              <span className={`px-2 py-0.5 rounded-full text-xs ${
                activeTab === 'aired'
                  ? 'bg-cyan-100 dark:bg-cyan-900/30 text-cyan-700 dark:text-cyan-300'
                  : 'bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400'
              }`}>
                {airedCount}
              </span>
            )}
          </button>

          <button
            onClick={() => setActiveTab('watched')}
            className={`flex items-center gap-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
              activeTab === 'watched'
                ? 'border-cyan-500 text-cyan-600 dark:text-cyan-400'
                : 'border-transparent text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-100'
            }`}
          >
            <CheckCircle className="w-4 h-4" />
            Watched
            {watchedCount > 0 && (
              <span className={`px-2 py-0.5 rounded-full text-xs ${
                activeTab === 'watched'
                  ? 'bg-cyan-100 dark:bg-cyan-900/30 text-cyan-700 dark:text-cyan-300'
                  : 'bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400'
              }`}>
                {watchedCount}
              </span>
            )}
          </button>

          <button
            onClick={() => setActiveTab('all')}
            className={`flex items-center gap-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
              activeTab === 'all'
                ? 'border-cyan-500 text-cyan-600 dark:text-cyan-400'
                : 'border-transparent text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-100'
            }`}
          >
            <Calendar className="w-4 h-4" />
            All
            {allAppearances && (
              <span className={`px-2 py-0.5 rounded-full text-xs ${
                activeTab === 'all'
                  ? 'bg-cyan-100 dark:bg-cyan-900/30 text-cyan-700 dark:text-cyan-300'
                  : 'bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400'
              }`}>
                {allAppearances.length}
              </span>
            )}
          </button>

          <button
            onClick={() => setActiveTab('notifications')}
            className={`flex items-center gap-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
              activeTab === 'notifications'
                ? 'border-cyan-500 text-cyan-600 dark:text-cyan-400'
                : 'border-transparent text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-slate-100'
            }`}
          >
            <Bell className="w-4 h-4" />
            Notifications
            {(notificationStats?.stats?.total ?? 0) > 0 && (
              <span className={`px-2 py-0.5 rounded-full text-xs ${
                activeTab === 'notifications'
                  ? 'bg-cyan-100 dark:bg-cyan-900/30 text-cyan-700 dark:text-cyan-300'
                  : 'bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400'
              }`}>
                {notificationStats?.stats?.total}
              </span>
            )}
          </button>
        </div>
      </div>

      {/* Sync Status Banner */}
      {syncProgress.is_running && (
        <div className="card-glass rounded-xl bg-gradient-to-r from-cyan-500/10 to-blue-500/10 border border-cyan-500/30 p-4">
          <div className="flex items-center justify-between mb-3">
            <div className="flex items-center gap-2">
              <div className="relative">
                <Calendar className="w-5 h-5 text-cyan-600 dark:text-cyan-400" />
                <span className="absolute -top-1 -right-1 w-2 h-2 bg-cyan-500 rounded-full animate-pulse"></span>
              </div>
              <h3 className="text-sm font-semibold text-cyan-900 dark:text-cyan-100">
                Syncing Appearances
              </h3>
            </div>
            <span className="text-xs text-cyan-600 dark:text-cyan-400">
              {syncProgress.total_celebrities || 0} celebrities
            </span>
          </div>

          {syncProgress.current_celebrity && (
            <div className="mb-3 px-3 py-2 bg-cyan-100 dark:bg-cyan-900/30 rounded-lg space-y-2">
              <div className="flex items-center justify-between gap-2 text-sm text-cyan-800 dark:text-cyan-200">
                <div className="flex items-center gap-2">
                  <span className="w-2 h-2 bg-cyan-500 rounded-full animate-pulse"></span>
                  <span className="truncate font-medium">{syncProgress.current_celebrity}</span>
                </div>
                {syncProgress.phase && (
                  <span className="text-xs text-cyan-600 dark:text-cyan-400">
                    {syncProgress.phase === 'fetching_movies' && 'Fetching movies...'}
                    {syncProgress.phase === 'fetching_tv' && 'Fetching TV shows...'}
                    {syncProgress.phase === 'fetching_podcasts' && 'Fetching podcasts (Podchaser)...'}
                    {syncProgress.phase === 'fetching_podcasts_taddy' && 'Fetching podcasts (Taddy)...'}
                    {syncProgress.phase === 'fetching' && 'Fetching data...'}
                    {syncProgress.phase === 'saving' && 'Saving to database...'}
                  </span>
                )}
              </div>
              {/* Show-level progress for TV */}
              {syncProgress.phase === 'fetching_tv' && (syncProgress.total_shows || 0) > 0 && (
                <div className="pl-4">
                  <div className="flex items-center justify-between text-xs text-cyan-700 dark:text-cyan-300 mb-1">
                    <span className="truncate max-w-[200px]">{syncProgress.current_show || 'Loading...'}</span>
                    <span>{syncProgress.shows_processed || 0}/{syncProgress.total_shows || 0}</span>
                  </div>
                  <div className="w-full bg-cyan-300 dark:bg-cyan-700 rounded-full h-1.5">
                    <div
                      className="bg-cyan-500 dark:bg-cyan-300 h-1.5 rounded-full transition-all duration-200"
                      style={{ width: `${((syncProgress.shows_processed || 0) / (syncProgress.total_shows || 1) * 100)}%` }}
                    ></div>
                  </div>
                </div>
              )}
              {/* Podcast-level progress for Podchaser/Taddy */}
              {(syncProgress.phase === 'fetching_podcasts' || syncProgress.phase === 'fetching_podcasts_taddy') && (syncProgress.total_podcasts || 0) > 0 && (
                <div className="pl-4">
                  <div className="flex items-center justify-between text-xs text-cyan-700 dark:text-cyan-300 mb-1">
                    <span className="truncate max-w-[200px]">{syncProgress.current_podcast || 'Loading...'}</span>
                    <span>{syncProgress.podcasts_processed || 0}/{syncProgress.total_podcasts || 0}</span>
                  </div>
                  <div className="w-full bg-green-300 dark:bg-green-700 rounded-full h-1.5">
                    <div
                      className="bg-green-500 dark:bg-green-300 h-1.5 rounded-full transition-all duration-200"
                      style={{ width: `${((syncProgress.podcasts_processed || 0) / (syncProgress.total_podcasts || 1) * 100)}%` }}
                    ></div>
                  </div>
                </div>
              )}
            </div>
          )}

          <div className="mb-2">
            <div className="flex justify-between text-xs text-cyan-700 dark:text-cyan-300 mb-1">
              <span>Progress</span>
              <span>{syncProgress.celebrities_processed || 0}/{syncProgress.total_celebrities || 0}</span>
            </div>
            <div className="w-full bg-cyan-200 dark:bg-cyan-800 rounded-full h-1.5 sm:h-2">
              <div
                className="bg-cyan-600 dark:bg-cyan-400 h-1.5 sm:h-2 rounded-full transition-all duration-300"
                style={{ width: `${syncProgress.total_celebrities > 0 ? (syncProgress.celebrities_processed / syncProgress.total_celebrities * 100) : 0}%` }}
              ></div>
            </div>
          </div>

          {syncProgress.new_appearances > 0 && (
            <div className="flex items-center gap-1.5 text-xs text-green-700 dark:text-green-300 font-medium">
              <svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
              </svg>
              <span>Found {syncProgress.new_appearances} new appearance{syncProgress.new_appearances !== 1 ? 's' : ''}</span>
            </div>
          )}
        </div>
      )}

      {/* Plex Stats Card - Show when we have matched items */}
      {plexStats && plexStats.matched > 0 && (
        <div className="card-glass rounded-xl bg-gradient-to-r from-amber-500/10 to-orange-500/10 border border-amber-500/30 p-4">
          <div className="flex items-center gap-2 mb-3">
            <MonitorPlay className="w-5 h-5 text-amber-600 dark:text-amber-400" />
            <h3 className="text-sm font-semibold text-amber-900 dark:text-amber-100">
              Plex Library
            </h3>
            <span className="ml-auto text-xs text-amber-600 dark:text-amber-400">
              {plexStats.percentage}% matched
            </span>
          </div>
          <div className="w-full bg-amber-200 dark:bg-amber-800 rounded-full h-1.5 sm:h-2 mb-3">
            <div
              className="bg-amber-600 dark:bg-amber-400 h-1.5 sm:h-2 rounded-full transition-all duration-300"
              style={{ width: `${plexStats.percentage}%` }}
            ></div>
          </div>
          <div className="grid grid-cols-3 gap-4 text-center text-xs">
            <div>
              <p className="font-medium text-amber-900 dark:text-amber-100">{plexStats.matched}</p>
              <p className="text-amber-600 dark:text-amber-400">In Library</p>
            </div>
            <div>
              <p className="font-medium text-slate-600 dark:text-slate-400">{plexStats.unmatched}</p>
              <p className="text-slate-500 dark:text-slate-500">Not Found</p>
            </div>
            <div>
              <p className="font-medium text-slate-900 dark:text-slate-100">{plexStats.total}</p>
              <p className="text-slate-500 dark:text-slate-500">Total</p>
            </div>
          </div>
          {plexStats.breakdown && (
            <div className="mt-3 text-xs text-amber-700 dark:text-amber-300">
              {plexStats.breakdown.Movie && (
                <span className="mr-3">Movies: {plexStats.breakdown.Movie.matched}/{plexStats.breakdown.Movie.total}</span>
              )}
              {plexStats.breakdown.TV && (
                <span>TV: {plexStats.breakdown.TV.matched}/{plexStats.breakdown.TV.total}</span>
              )}
            </div>
          )}
        </div>
      )}

      {/* Filters - hidden on notifications tab */}
      {activeTab !== 'notifications' && (
        <div className="card-glass-hover rounded-xl p-4 relative z-30">
          <FilterBar
            searchValue={searchQuery}
            onSearchChange={setSearchQuery}
            searchPlaceholder="Search shows, celebrities..."
            filterSections={[
              {
                id: 'celebrity',
                label: 'Celebrity',
                type: 'select',
                options: [
                  { value: 'all', label: 'All Celebrities' },
                  ...uniqueCelebrities.map(c => ({ value: c, label: c }))
                ],
                value: selectedCelebrity,
                onChange: (v) => setSelectedCelebrity(v as string)
              },
              {
                id: 'type',
                label: 'Appearance Type',
                type: 'select',
                options: [
                  { value: 'all', label: 'All Types' },
                  { value: 'TV', label: 'TV Shows' },
                  { value: 'Movie', label: 'Movies' },
                  { value: 'Podcast', label: 'Podcasts' },
                  { value: 'Radio', label: 'Radio' }
                ],
                value: selectedType,
                onChange: (v) => setSelectedType(v as string)
              },
              {
                id: 'creditType',
                label: 'Credit Type',
                type: 'select',
                options: [
                  { value: 'all', label: 'All Credits' },
                  { value: 'acting', label: 'Acting' },
                  { value: 'directing', label: 'Directing' },
                  { value: 'producing', label: 'Producing' },
                  { value: 'writing', label: 'Writing' },
                  { value: 'creator', label: 'Creator' },
                  { value: 'guest', label: 'Guest' },
                  { value: 'host', label: 'Host' }
                ],
                value: selectedCreditType,
                onChange: (v) => setSelectedCreditType(v as string)
              },
              {
                id: 'dateFilter',
                label: 'Date Range',
                type: 'select',
                options: [
                  { value: 'all', label: 'All Dates' },
                  { value: '7days', label: 'Within 7 Days' },
                  { value: '30days', label: 'Within 30 Days' },
                  { value: 'custom', label: 'Custom Range' }
                ],
                value: dateFilter,
                onChange: (v) => setDateFilter(v as 'all' | '7days' | '30days' | 'custom')
              },
              {
                id: 'plexOnly',
                label: 'Library',
                type: 'select',
                options: [
                  { value: 'false', label: 'All Libraries' },
                  { value: 'true', label: 'On Plex Only' }
                ],
                value: plexOnly ? 'true' : 'false',
                onChange: (v) => setPlexOnly(v === 'true')
              }
            ]}
            activeFilters={[
              ...(selectedCelebrity !== 'all' ? [{
                id: 'celebrity',
                label: 'Celebrity',
                value: selectedCelebrity,
                displayValue: selectedCelebrity,
                onRemove: () => setSelectedCelebrity('all')
              }] : []),
              ...(selectedType !== 'all' ? [{
                id: 'type',
                label: 'Type',
                value: selectedType,
                displayValue: selectedType === 'TV' ? 'TV Shows' : selectedType === 'Movie' ? 'Movies' : selectedType === 'Podcast' ? 'Podcasts' : 'Radio',
                onRemove: () => setSelectedType('all')
              }] : []),
              ...(selectedCreditType !== 'all' ? [{
                id: 'creditType',
                label: 'Credit',
                value: selectedCreditType,
                displayValue: creditTypeConfig[selectedCreditType as keyof typeof creditTypeConfig]?.label || selectedCreditType,
                onRemove: () => setSelectedCreditType('all')
              }] : []),
              ...(dateFilter !== 'all' ? [{
                id: 'dateFilter',
                label: 'Date',
                value: dateFilter,
                displayValue: dateFilter === '7days' ? 'Within 7 Days' : dateFilter === '30days' ? 'Within 30 Days' : 'Custom Range',
                onRemove: () => {
                  setDateFilter('all')
                  setCustomStartDate('')
                  setCustomEndDate('')
                }
              }] : []),
              ...(plexOnly ? [{
                id: 'plexOnly',
                label: 'Library',
                value: 'true',
                displayValue: 'On Plex',
                onRemove: () => setPlexOnly(false)
              }] : [])
            ]}
            onClearAll={() => {
              setSearchQuery('')
              setSelectedCelebrity('all')
              setSelectedType('all')
              setSelectedCreditType('all')
              setDateFilter('all')
              setCustomStartDate('')
              setCustomEndDate('')
              setPlexOnly(false)
            }}
            totalCount={filteredAppearances.length}
            countLabel="results"
            advancedFilters={dateFilter === 'custom' ? {
              dateFrom: {
                value: customStartDate,
                onChange: setCustomStartDate,
                label: 'Start Date'
              },
              dateTo: {
                value: customEndDate,
                onChange: setCustomEndDate,
                label: 'End Date'
              }
            } : undefined}
          />
        </div>
      )}

      {/* Results */}
      <div className="card-glass rounded-xl p-4 md:p-6">
        <div className="flex items-center justify-between mb-4">
          <h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100">
            {activeTab === 'upcoming' && 'Upcoming Appearances'}
            {activeTab === 'aired' && 'Aired Appearances'}
            {activeTab === 'watched' && 'Watched Appearances'}
            {activeTab === 'all' && 'All Appearances'}
            {activeTab === 'notifications' && 'Notification History'}
          </h3>
          <span className="text-xs text-slate-500 dark:text-slate-400 bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
            {activeTab === 'notifications'
              ? `${notificationsData?.total || 0} notifications`
              : `${filteredAppearances.length} results`
            }
          </span>
        </div>

        {/* Notifications Tab Content */}
        {activeTab === 'notifications' ? (
          notificationsLoading ? (
            <div className="flex items-center justify-center py-12">
              <Loader2 className="w-8 h-8 animate-spin text-blue-600" />
            </div>
          ) : !notificationsData?.notifications?.length ? (
            <div className="text-center py-12">
              <Bell className="w-16 h-16 mx-auto mb-4 text-slate-300 dark:text-slate-600" />
              <p className="text-slate-600 dark:text-slate-400">
                No notifications sent yet
              </p>
              <p className="text-sm text-slate-500 dark:text-slate-500 mt-1">
                Notifications will appear here when reminders are sent for upcoming appearances
              </p>
            </div>
          ) : (
            <div className="space-y-3">
              {/* Notification Stats */}
              {notificationStats?.stats && (
                <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
                  <div className="card-glass-hover rounded-xl p-4 border stat-card-green shadow-green-glow">
                    <div className="flex items-center justify-between">
                      <div>
                        <p className="text-sm text-muted-foreground">Total Sent</p>
                        <p className="text-2xl font-bold text-emerald-600 dark:text-emerald-400">
                          {notificationStats.stats.total}
                        </p>
                      </div>
                      <div className="p-3 rounded-xl bg-emerald-500/20">
                        <Bell className="w-6 h-6 text-emerald-600 dark:text-emerald-400" />
                      </div>
                    </div>
                  </div>
                  <div className="card-glass-hover rounded-xl p-4 border stat-card-blue shadow-blue-glow">
                    <div className="flex items-center justify-between">
                      <div>
                        <p className="text-sm text-muted-foreground">Today</p>
                        <p className="text-2xl font-bold text-blue-600 dark:text-blue-400">
                          {notificationStats.stats.today}
                        </p>
                      </div>
                      <div className="p-3 rounded-xl bg-blue-500/20">
                        <Clock className="w-6 h-6 text-blue-600 dark:text-blue-400" />
                      </div>
                    </div>
                  </div>
                  <div className="card-glass-hover rounded-xl p-4 border stat-card-purple shadow-purple-glow">
                    <div className="flex items-center justify-between">
                      <div>
                        <p className="text-sm text-muted-foreground">Types</p>
                        <p className="text-2xl font-bold text-violet-600 dark:text-violet-400">
                          {Object.keys(notificationStats.stats.by_type || {}).length}
                        </p>
                      </div>
                      <div className="p-3 rounded-xl bg-violet-500/20">
                        <Filter className="w-6 h-6 text-violet-600 dark:text-violet-400" />
                      </div>
                    </div>
                  </div>
                </div>
              )}

              {/* Notification List */}
              {notificationsData.notifications.map((notification) => (
                <div
                  key={notification.id}
                  className="card-glass-hover rounded-xl p-4"
                >
                  <div className="flex items-start gap-4">
                    {/* Poster on left - use cached endpoint */}
                    {(notification.appearance_id || notification.poster_url) && (
                      <img
                        src={notification.appearance_id
                          ? `/api/appearances/poster/${notification.appearance_id}`
                          : (notification.poster_url?.startsWith('http')
                              ? notification.poster_url
                              : `https://image.tmdb.org/t/p/w92${notification.poster_url}`)}
                        alt={notification.show_name}
                        className="w-12 h-12 object-cover rounded-lg flex-shrink-0"
                        onError={(e) => {
                          (e.target as HTMLImageElement).style.display = 'none'
                        }}
                      />
                    )}

                    {/* Content */}
                    <div className="flex-1 min-w-0">
                      {/* Header with icon, show name, and status badge */}
                      <div className="flex items-center space-x-3 mb-2">
                        {notification.notification_type === 'reminder' ? (
                          <Clock className="w-5 h-5 text-blue-600 dark:text-blue-400" />
                        ) : notification.notification_type === 'plex_match' ? (
                          <MonitorPlay className="w-5 h-5 text-amber-600 dark:text-amber-400" />
                        ) : (
                          <Bell className="w-5 h-5 text-green-600 dark:text-green-400" />
                        )}
                        <h3 className="font-semibold text-slate-900 dark:text-slate-100 truncate">
                          {notification.show_name}
                        </h3>
                        <span className="px-2 py-0.5 text-xs font-medium rounded-full bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400 flex-shrink-0">
                          sent
                        </span>
                      </div>

                      {/* Message content with HTML formatting (sanitized) */}
                      <div
                        className="text-sm text-slate-600 dark:text-slate-400 mb-3 whitespace-pre-wrap [&_b]:font-semibold [&_b]:text-slate-700 dark:[&_b]:text-slate-300"
                        dangerouslySetInnerHTML={{ __html: sanitizeHtml(notification.message) }}
                      />

                      {/* Meta info row */}
                      <div className="flex flex-wrap gap-3 text-xs text-slate-500 dark:text-slate-400">
                        <span>
                          Type: <span className="font-medium">
                            {notification.notification_type === 'reminder'
                              ? 'Reminder'
                              : notification.notification_type === 'plex_match'
                                ? 'Plex Match'
                                : 'New'
                            }
                          </span>
                        </span>
                        <span>
                          Category: <span className="font-medium">{notification.appearance_type}</span>
                        </span>
                      </div>
                    </div>

                    {/* Right side - time and Plex button */}
                    <div className="flex flex-col items-end gap-2 flex-shrink-0">
                      <div className="text-xs text-slate-500 dark:text-slate-400">
                        {notification.sent_at ? format(parseISO(notification.sent_at), 'MMM d, h:mm a') : 'Pending'}
                      </div>
                      {notification.plex_watch_url && (
                        <a
                          href={notification.plex_watch_url}
                          target="_blank"
                          rel="noopener noreferrer"
                          className="flex items-center gap-1.5 px-3 py-1.5 bg-amber-500 hover:bg-amber-600 text-white text-xs font-medium rounded-lg transition-colors"
                          title="Watch on Plex"
                        >
                          <MonitorPlay className="w-3.5 h-3.5" />
                          Plex
                        </a>
                      )}
                    </div>
                  </div>
                </div>
              ))}
            </div>
          )
        ) : isLoading ? (
          <div className="flex items-center justify-center py-12">
            <Loader2 className="w-8 h-8 animate-spin text-blue-600" />
          </div>
        ) : filteredAppearances.length === 0 ? (
          <div className="text-center py-12">
            <Calendar className="w-16 h-16 mx-auto mb-4 text-slate-300 dark:text-slate-600" />
            <p className="text-slate-600 dark:text-slate-400">
              {activeTab === 'upcoming' && 'No upcoming appearances'}
              {activeTab === 'aired' && 'No aired appearances'}
              {activeTab === 'watched' && 'No watched appearances'}
              {activeTab === 'all' && 'No appearances found'}
            </p>
            <p className="text-sm text-slate-500 dark:text-slate-500 mt-1">
              Try syncing with TMDb or adjusting filters
            </p>
          </div>
        ) : (
          <div className="space-y-3">
            {filteredAppearances.map((appearance) => {
              const config = typeConfig[appearance.appearance_type]
              const Icon = config.icon
              const isPast = isBefore(parseISO(appearance.appearance_date), new Date())
              const isSoon = !isPast && isBefore(parseISO(appearance.appearance_date), new Date(Date.now() + 7 * 24 * 60 * 60 * 1000))

              return (
                <div
                  key={appearance.id}
                  onClick={() => setSelectedAppearance(appearance)}
                  className="flex flex-col sm:flex-row sm:items-center sm:justify-between p-3 sm:p-4 card-glass-hover rounded-xl group cursor-pointer transition-all gap-3"
                >
                  {/* Poster/Icon + Info */}
                  <div className="flex items-center gap-3 sm:gap-4 min-w-0 flex-1">
                    {appearance.poster_url ? (
                      <div className="w-10 h-10 sm:w-12 sm:h-12 rounded-lg overflow-hidden flex-shrink-0 bg-slate-200 dark:bg-slate-700">
                        <img
                          src={`/api/appearances/poster/${appearance.id}`}
                          alt={appearance.show_name}
                          className="w-full h-full object-cover"
                          onError={(e) => {
                            e.currentTarget.style.display = 'none'
                            const parent = e.currentTarget.parentElement
                            if (parent) {
                              parent.innerHTML = `<div class="w-12 h-12 ${config.color} rounded-lg flex items-center justify-center"><svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="${config.icon === Tv ? 'M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4m18-10H3m18 0v10M3 5v10' : config.icon === Mic ? 'M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z' : 'M7 4v16M17 4v16M3 8h18M3 16h18'}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>`
                            }
                          }}
                        />
                      </div>
                    ) : (
                      <div className={`w-10 h-10 sm:w-12 sm:h-12 ${config.color} rounded-lg flex items-center justify-center flex-shrink-0`}>
                        <Icon className="w-5 h-5 sm:w-6 sm:h-6 text-white" />
                      </div>
                    )}

                    <div className="min-w-0 flex-1">
                      <div className="flex items-center gap-2 mb-1 flex-wrap">
                        <p className="text-sm font-semibold text-foreground truncate">
                          {appearance.celebrity_name}
                        </p>
                        <span className="text-xs px-2 py-0.5 bg-blue-500/10 text-blue-600 dark:text-blue-400 rounded flex-shrink-0">
                          {config.label}
                        </span>
                        {/* Credit Type Badges */}
                        {(appearance.all_credit_types || (appearance.credit_type ? [appearance.credit_type] : [])).map((creditType) => {
                          const creditConfig = creditTypeConfig[creditType as keyof typeof creditTypeConfig]
                          if (!creditConfig) return null
                          const CreditIcon = creditConfig.icon
                          return (
                            <span
                              key={creditType}
                              className={`text-xs px-2 py-0.5 rounded flex items-center gap-1 flex-shrink-0 ${creditConfig.color}`}
                              title={creditType === 'acting' ? appearance.character_name || undefined : appearance.job_title || undefined}
                            >
                              <CreditIcon className="w-3 h-3" />
                              {creditConfig.label}
                            </span>
                          )
                        })}
                        {(appearance.appearance_type === 'Podcast' || appearance.appearance_type === 'TV') && appearance.episode_count > 1 && (
                          <span className="text-xs px-2 py-0.5 bg-purple-500/10 text-purple-600 dark:text-purple-400 rounded flex-shrink-0">
                            {appearance.episode_count} episodes
                          </span>
                        )}
                        {appearance.status === 'watched' && (
                          <span className="text-xs px-2 py-0.5 bg-green-500/10 text-green-600 dark:text-green-400 rounded flex items-center gap-1 flex-shrink-0">
                            <CheckCircle className="w-3 h-3" />
                            Watched
                          </span>
                        )}
                        {isSoon && appearance.status === 'upcoming' && (
                          <span className="text-xs px-2 py-0.5 bg-orange-500/10 text-orange-600 dark:text-orange-400 rounded flex-shrink-0">
                            Soon
                          </span>
                        )}
                        {/* Plex Available Badge */}
                        {appearance.plex_watch_url && (
                          <span className="text-xs px-2 py-0.5 bg-yellow-500/10 text-yellow-600 dark:text-yellow-400 rounded flex items-center gap-1 flex-shrink-0">
                            <Play className="w-3 h-3" />
                            Plex
                          </span>
                        )}
                      </div>
                      <p className="text-sm text-foreground truncate">
                        {appearance.show_name}
                        {appearance.network && (
                          <span className="text-muted-foreground"> • {appearance.network}</span>
                        )}
                      </p>
                      {/* Character/Job Info */}
                      {(appearance.character_name || appearance.job_title) && (
                        <p className="text-xs text-muted-foreground truncate mt-0.5">
                          {appearance.credit_type === 'acting' && appearance.character_name && (
                            <span>as {appearance.character_name}</span>
                          )}
                          {appearance.credit_type !== 'acting' && appearance.job_title && (
                            <span>{appearance.job_title}</span>
                          )}
                        </p>
                      )}
                      {appearance.episode_title && (
                        <p className="text-xs text-muted-foreground truncate mt-0.5">
                          {appearance.season_number && appearance.episode_number && (
                            <span>S{appearance.season_number}E{appearance.episode_number}: </span>
                          )}
                          {appearance.episode_title}
                        </p>
                      )}
                    </div>
                  </div>

                  {/* Plex + Date + Actions */}
                  <div className="flex items-center justify-between sm:justify-end gap-2 sm:gap-3 sm:ml-4 flex-shrink-0 pl-12 sm:pl-0">
                    {/* Plex Watch Button - fixed width column for alignment */}
                    <div className="w-14 sm:w-16 flex-shrink-0">
                      {appearance.plex_watch_url && (
                        <a
                          href={appearance.plex_watch_url}
                          target="_blank"
                          rel="noopener noreferrer"
                          onClick={(e) => e.stopPropagation()}
                          className="px-2 py-1.5 bg-gradient-to-r from-amber-600 to-orange-600 hover:from-amber-700 hover:to-orange-700 text-white rounded-lg transition-colors flex items-center gap-1 text-xs font-medium"
                          title="Watch on Plex"
                        >
                          <MonitorPlay className="w-3.5 h-3.5" />
                          Plex
                        </a>
                      )}
                    </div>

                    <div className="text-right w-20 sm:w-24">
                      <p className="text-xs font-medium text-foreground">
                        {appearance.appearance_date.startsWith('1900') ? 'Coming Soon' : format(parseISO(appearance.appearance_date), 'MMM d, yyyy')}
                      </p>
                      <p className="text-xs text-muted-foreground">
                        {appearance.appearance_date.startsWith('1900') ? (
                          'In Production'
                        ) : isPast ? (
                          formatDistanceToNow(parseISO(appearance.appearance_date), { addSuffix: true })
                        ) : (
                          formatDistanceToNow(parseISO(appearance.appearance_date), { addSuffix: true })
                        )}
                      </p>
                    </div>

                    {/* Quick Actions */}
                    <div className="flex items-center gap-1">
                      {appearance.status !== 'watched' && (
                        <button
                          onClick={(e) => {
                            e.stopPropagation()
                            markWatchedMutation.mutate(appearance.id)
                          }}
                          className="p-2 hover:bg-green-500/10 rounded-lg transition-colors group/btn"
                          title="Mark as watched"
                        >
                          <Eye className="w-4 h-4 text-muted-foreground group-hover/btn:text-green-600" />
                        </button>
                      )}
                      {appearance.status !== 'ignored' && (
                        <button
                          onClick={(e) => {
                            e.stopPropagation()
                            markIgnoredMutation.mutate(appearance.id)
                          }}
                          className="p-2 hover:bg-slate-500/10 rounded-lg transition-colors group/btn"
                          title="Mark as ignored"
                        >
                          <EyeOff className="w-4 h-4 text-muted-foreground group-hover/btn:text-slate-600" />
                        </button>
                      )}
                      <ChevronRight className="w-4 h-4 text-muted-foreground group-hover:text-foreground transition-colors" />
                    </div>
                  </div>
                </div>
              )
            })}
          </div>
        )}
      </div>

      {/* Detail Modal */}
      {selectedAppearance && (
        <AppearanceDetailModal
          appearance={selectedAppearance}
          onClose={() => setSelectedAppearance(null)}
          onMarkWatched={(id) => {
            markWatchedMutation.mutate(id)
            setSelectedAppearance(null)
          }}
        />
      )}
    </div>
  )
}
