'use client'

import { useState, useMemo, useCallback } from 'react'
import { trpc } from '@/lib/trpc/client'
import { Button } from '@/components/ui/button'
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Badge } from '@/components/ui/badge'
import { Skeleton } from '@/components/ui/skeleton'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from '@/components/ui/collapsible'
import {
  Download,
  Filter,
  ChevronDown,
  ChevronUp,
  Clock,
  User,
  Activity,
  Database,
  Globe,
  ChevronLeft,
  ChevronRight,
  RefreshCw,
  RotateCcw,
  AlertTriangle,
  Layers,
  ArrowLeftRight,
} from 'lucide-react'
import { Switch } from '@/components/ui/switch'
import { CsvExportDialog } from '@/components/shared/csv-export-dialog'
import { formatDate } from '@/lib/utils'
import { cn } from '@/lib/utils'
import Link from 'next/link'

// Action type options (manual audit actions + auto-generated mutation audit actions)
const ACTION_TYPES = [
  // Manual audit actions
  'CREATE',
  'UPDATE',
  'DELETE',
  'IMPORT',
  'EXPORT',
  'LOGIN',
  'LOGIN_SUCCESS',
  'LOGIN_FAILED',
  'INVITATION_ACCEPTED',
  'SUBMIT_EVALUATION',
  'EVALUATION_SUBMITTED',
  'UPDATE_STATUS',
  'ROUND_ACTIVATED',
  'ROUND_CLOSED',
  'ROUND_ARCHIVED',
  'UPLOAD_FILE',
  'DELETE_FILE',
  'FILE_VIEWED',
  'FILE_OPENED',
  'FILE_DOWNLOADED',
  'BULK_CREATE',
  'BULK_UPDATE_STATUS',
  'UPDATE_EVALUATION_FORM',
  'ROLE_CHANGED',
  'PASSWORD_SET',
  'PASSWORD_CHANGED',
  'JUROR_DROPOUT_RESHUFFLE',
  'COI_REASSIGNMENT',
  'APPLY_AI_SUGGESTIONS',
  'APPLY_SUGGESTIONS',
  'NOTIFY_JURORS_OF_ASSIGNMENTS',
  'IMPERSONATION_START',
  'IMPERSONATION_END',
  // Auto-generated mutation audit actions (non-super-admin)
  'EVALUATION_START',
  'EVALUATION_SUBMIT',
  'EVALUATION_AUTOSAVE',
  'EVALUATION_DECLARE_COI',
  'EVALUATION_ADD_COMMENT',
  'APPLICANT_SAVE_SUBMISSION',
  'APPLICANT_SAVE_FILE_METADATA',
  'APPLICANT_DELETE_FILE',
  'APPLICANT_REQUEST_MENTORING',
  'APPLICANT_WITHDRAW_FROM_COMPETITION',
  'APPLICANT_INVITE_TEAM_MEMBER',
  'APPLICANT_REMOVE_TEAM_MEMBER',
  'APPLICANT_SEND_MENTOR_MESSAGE',
  'APPLICATION_SUBMIT',
  'APPLICATION_SAVE_DRAFT',
  'APPLICATION_SUBMIT_DRAFT',
  'MENTOR_SEND_MESSAGE',
  'MENTOR_CREATE_NOTE',
  'MENTOR_DELETE_NOTE',
  'MENTOR_COMPLETE_MILESTONE',
  'LIVE_CAST_VOTE',
  'LIVE_CAST_STAGE_VOTE',
  'LIVE_VOTING_VOTE',
  'LIVE_VOTING_CAST_AUDIENCE_VOTE',
  'DELIBERATION_SUBMIT_VOTE',
  'NOTIFICATION_MARK_AS_READ',
  'NOTIFICATION_MARK_ALL_AS_READ',
  'USER_UPDATE_PROFILE',
  'USER_SET_PASSWORD',
  'USER_CHANGE_PASSWORD',
  'USER_COMPLETE_ONBOARDING',
  'SPECIAL_AWARD_SUBMIT_VOTE',
  // Security events
  'ACCOUNT_LOCKED',
  'ACCESS_DENIED_FORBIDDEN',
  'ACCESS_DENIED_UNAUTHORIZED',
  'ACCESS_DENIED_NOT_FOUND',
]

// Entity type options
const ENTITY_TYPES = [
  'User',
  'Program',
  'Competition',
  'Round',
  'Project',
  'Assignment',
  'Evaluation',
  'EvaluationForm',
  'ProjectFile',
  'GracePeriod',
  'Applicant',
  'Application',
  'Mentor',
  'Live',
  'LiveVoting',
  'Deliberation',
  'Notification',
  'SpecialAward',
  'File',
  'Tag',
  'Message',
  'Settings',
  'Ranking',
  'Filtering',
  'RoundEngine',
]

// Color map for action types
const actionColors: Record<string, 'default' | 'destructive' | 'secondary' | 'outline'> = {
  CREATE: 'default',
  UPDATE: 'secondary',
  DELETE: 'destructive',
  IMPORT: 'default',
  EXPORT: 'outline',
  LOGIN: 'outline',
  LOGIN_SUCCESS: 'outline',
  LOGIN_FAILED: 'destructive',
  INVITATION_ACCEPTED: 'default',
  SUBMIT_EVALUATION: 'default',
  EVALUATION_SUBMITTED: 'default',
  ROUND_ACTIVATED: 'default',
  ROUND_CLOSED: 'secondary',
  ROUND_ARCHIVED: 'secondary',
  FILE_VIEWED: 'outline',
  FILE_OPENED: 'outline',
  FILE_DOWNLOADED: 'outline',
  ROLE_CHANGED: 'secondary',
  PASSWORD_SET: 'outline',
  PASSWORD_CHANGED: 'outline',
  JUROR_DROPOUT_RESHUFFLE: 'destructive',
  COI_REASSIGNMENT: 'secondary',
  APPLY_AI_SUGGESTIONS: 'default',
  APPLY_SUGGESTIONS: 'default',
  NOTIFY_JURORS_OF_ASSIGNMENTS: 'outline',
  IMPERSONATION_START: 'destructive',
  IMPERSONATION_END: 'secondary',
  // Auto-generated mutation audit actions
  EVALUATION_START: 'default',
  EVALUATION_SUBMIT: 'default',
  EVALUATION_AUTOSAVE: 'outline',
  EVALUATION_DECLARE_COI: 'secondary',
  EVALUATION_ADD_COMMENT: 'outline',
  APPLICANT_SAVE_SUBMISSION: 'default',
  APPLICANT_DELETE_FILE: 'destructive',
  APPLICANT_WITHDRAW_FROM_COMPETITION: 'destructive',
  APPLICANT_INVITE_TEAM_MEMBER: 'default',
  APPLICANT_REMOVE_TEAM_MEMBER: 'destructive',
  APPLICATION_SUBMIT: 'default',
  MENTOR_SEND_MESSAGE: 'outline',
  MENTOR_CREATE_NOTE: 'default',
  MENTOR_DELETE_NOTE: 'destructive',
  LIVE_CAST_VOTE: 'default',
  LIVE_CAST_STAGE_VOTE: 'default',
  LIVE_VOTING_CAST_AUDIENCE_VOTE: 'default',
  DELIBERATION_SUBMIT_VOTE: 'default',
  SPECIAL_AWARD_SUBMIT_VOTE: 'default',
  USER_UPDATE_PROFILE: 'secondary',
  USER_SET_PASSWORD: 'outline',
  USER_CHANGE_PASSWORD: 'outline',
  USER_COMPLETE_ONBOARDING: 'default',
  // Security events
  ACCOUNT_LOCKED: 'destructive',
  ACCESS_DENIED_FORBIDDEN: 'destructive',
  ACCESS_DENIED_UNAUTHORIZED: 'destructive',
  ACCESS_DENIED_NOT_FOUND: 'secondary',
}


function getEntityLink(entityType: string, entityId: string): string | null {
  switch (entityType) {
    case 'User':
      return `/admin/members/${entityId}`
    case 'Project':
      return `/admin/projects/${entityId}`
    case 'Round':
      return `/admin/rounds/${entityId}`
    case 'Competition':
      return `/admin/competitions`
    case 'Evaluation':
    case 'EvaluationForm':
      return null // no dedicated page
    case 'SpecialAward':
      return `/admin/awards/${entityId}`
    default:
      return null
  }
}

export default function AuditLogPage() {
  // Filter state
  const [filters, setFilters] = useState({
    userId: '',
    action: '',
    entityType: '',
    startDate: '',
    endDate: '',
  })
  const [page, setPage] = useState(1)
  const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set())
  const [showFilters, setShowFilters] = useState(true)
  const [groupBySession, setGroupBySession] = useState(false)

  // Build query input
  const queryInput = useMemo(
    () => ({
      userId: filters.userId || undefined,
      action: filters.action || undefined,
      entityType: filters.entityType || undefined,
      startDate: filters.startDate ? new Date(filters.startDate) : undefined,
      endDate: filters.endDate
        ? new Date(filters.endDate + 'T23:59:59')
        : undefined,
      page,
      perPage: 50,
    }),
    [filters, page]
  )

  // Fetch audit logs
  const { data, isLoading, refetch } = trpc.audit.list.useQuery(queryInput, { refetchInterval: 30_000 })

  // Fetch users for filter dropdown
  const { data: usersData } = trpc.user.list.useQuery({
    page: 1,
    perPage: 100,
  })

  // Fetch anomalies
  const { data: anomalyData } = trpc.audit.getAnomalies.useQuery({}, {
    retry: false,
  })

  // Export query
  const exportLogs = trpc.export.auditLogs.useQuery(
    {
      userId: filters.userId || undefined,
      action: filters.action || undefined,
      entityType: filters.entityType || undefined,
      startDate: filters.startDate ? new Date(filters.startDate) : undefined,
      endDate: filters.endDate
        ? new Date(filters.endDate + 'T23:59:59')
        : undefined,
    },
    { enabled: false }
  )
  const [showExportDialog, setShowExportDialog] = useState(false)

  // Handle export
  const handleExport = () => {
    setShowExportDialog(true)
  }

  const handleRequestExportData = useCallback(async () => {
    const result = await exportLogs.refetch()
    return result.data ?? undefined
  }, [exportLogs])

  // Reset filters
  const resetFilters = () => {
    setFilters({
      userId: '',
      action: '',
      entityType: '',
      startDate: '',
      endDate: '',
    })
    setPage(1)
  }

  // Toggle row expansion
  const toggleRow = (id: string) => {
    const newExpanded = new Set(expandedRows)
    if (newExpanded.has(id)) {
      newExpanded.delete(id)
    } else {
      newExpanded.add(id)
    }
    setExpandedRows(newExpanded)
  }

  const hasFilters = Object.values(filters).some((v) => v !== '')

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-semibold tracking-tight">Audit Logs</h1>
          <p className="text-muted-foreground">
            View system activity and user actions
          </p>
        </div>
        <div className="flex gap-2">
          <Button variant="outline" size="icon" onClick={() => refetch()}>
            <RefreshCw className="h-4 w-4" />
          </Button>
          <Button
            variant="outline"
            onClick={handleExport}
            disabled={exportLogs.isFetching}
          >
            <Download className="mr-2 h-4 w-4" />
            Export CSV
          </Button>
        </div>
      </div>

      {/* Filters */}
      <Collapsible open={showFilters} onOpenChange={setShowFilters}>
        <Card>
          <CollapsibleTrigger asChild>
            <CardHeader className="cursor-pointer hover:bg-muted/50 transition-colors">
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-2">
                  <Filter className="h-4 w-4" />
                  <CardTitle className="text-lg">Filters</CardTitle>
                  {hasFilters && (
                    <Badge variant="secondary" className="ml-2">
                      Active
                    </Badge>
                  )}
                </div>
                {showFilters ? (
                  <ChevronUp className="h-4 w-4" />
                ) : (
                  <ChevronDown className="h-4 w-4" />
                )}
              </div>
            </CardHeader>
          </CollapsibleTrigger>
          <CollapsibleContent>
            <CardContent className="space-y-4">
              <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-5">
                {/* User Filter */}
                <div className="space-y-2">
                  <Label>User</Label>
                  <Select
                    value={filters.userId}
                    onValueChange={(v) =>
                      setFilters({ ...filters, userId: v === '__all__' ? '' : v })
                    }
                  >
                    <SelectTrigger>
                      <SelectValue placeholder="All users" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="__all__">All users</SelectItem>
                      {usersData?.users.map((user) => (
                        <SelectItem key={user.id} value={user.id}>
                          {user.name || user.email}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>

                {/* Action Filter */}
                <div className="space-y-2">
                  <Label>Action</Label>
                  <Select
                    value={filters.action}
                    onValueChange={(v) =>
                      setFilters({ ...filters, action: v === '__all__' ? '' : v })
                    }
                  >
                    <SelectTrigger>
                      <SelectValue placeholder="All actions" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="__all__">All actions</SelectItem>
                      {ACTION_TYPES.map((action) => (
                        <SelectItem key={action} value={action}>
                          {action.replace(/_/g, ' ')}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>

                {/* Entity Type Filter */}
                <div className="space-y-2">
                  <Label>Entity Type</Label>
                  <Select
                    value={filters.entityType}
                    onValueChange={(v) =>
                      setFilters({ ...filters, entityType: v === '__all__' ? '' : v })
                    }
                  >
                    <SelectTrigger>
                      <SelectValue placeholder="All types" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="__all__">All types</SelectItem>
                      {ENTITY_TYPES.map((type) => (
                        <SelectItem key={type} value={type}>
                          {type}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>

                {/* Start Date */}
                <div className="space-y-2">
                  <Label>From Date</Label>
                  <Input
                    type="date"
                    value={filters.startDate}
                    onChange={(e) =>
                      setFilters({ ...filters, startDate: e.target.value })
                    }
                  />
                </div>

                {/* End Date */}
                <div className="space-y-2">
                  <Label>To Date</Label>
                  <Input
                    type="date"
                    value={filters.endDate}
                    onChange={(e) =>
                      setFilters({ ...filters, endDate: e.target.value })
                    }
                  />
                </div>
              </div>

              {hasFilters && (
                <div className="flex justify-end">
                  <Button variant="ghost" size="sm" onClick={resetFilters}>
                    <RotateCcw className="mr-2 h-4 w-4" />
                    Reset Filters
                  </Button>
                </div>
              )}
            </CardContent>
          </CollapsibleContent>
        </Card>
      </Collapsible>

      {/* Anomaly Alerts */}
      {anomalyData && anomalyData.anomalies.length > 0 && (
        <Card className="border-amber-500/50 bg-amber-500/5">
          <CardHeader className="pb-2">
            <CardTitle className="text-lg flex items-center gap-2 text-amber-700">
              <AlertTriangle className="h-5 w-5" />
              Anomaly Alerts ({anomalyData.anomalies.length})
            </CardTitle>
          </CardHeader>
          <CardContent>
            <div className="space-y-2">
              {anomalyData.anomalies.slice(0, 5).map((anomaly, i) => (
                <div key={i} className="flex items-start gap-3 rounded-lg border border-amber-200 bg-white p-3 text-sm">
                  <AlertTriangle className="h-4 w-4 text-amber-500 shrink-0 mt-0.5" />
                  <div className="flex-1 min-w-0">
                    <p className="font-medium">{anomaly.isRapid ? 'Rapid Activity' : 'Bulk Operations'}</p>
                    <p className="text-xs text-muted-foreground">{String(anomaly.actionCount)} actions in {String(anomaly.timeWindowMinutes)} min ({anomaly.actionsPerMinute.toFixed(1)}/min)</p>
                    {anomaly.userId && (
                      <p className="text-xs text-muted-foreground mt-1">
                        User: {String(anomaly.user?.name || anomaly.userId)}
                      </p>
                    )}
                  </div>
                  <span className="text-xs text-muted-foreground shrink-0">
                    {String(anomaly.actionCount)} actions
                  </span>
                </div>
              ))}
            </div>
          </CardContent>
        </Card>
      )}

      {/* Session Grouping Toggle */}
      <div className="flex items-center gap-3">
        <div className="flex items-center gap-2">
          <Switch
            id="session-grouping"
            checked={groupBySession}
            onCheckedChange={setGroupBySession}
          />
          <label htmlFor="session-grouping" className="text-sm cursor-pointer flex items-center gap-1">
            <Layers className="h-4 w-4" />
            Group by Session
          </label>
        </div>
      </div>

      {/* Results */}
      {isLoading ? (
        <AuditLogSkeleton />
      ) : data && data.logs.length > 0 ? (
        <>
          {/* Desktop Table View */}
          <Card className="hidden md:block">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead className="w-[180px]">Timestamp</TableHead>
                  <TableHead>User</TableHead>
                  <TableHead>Action</TableHead>
                  <TableHead>Entity</TableHead>
                  <TableHead>IP Address</TableHead>
                  <TableHead className="w-[50px]"></TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {data.logs.map((log) => {
                  const isExpanded = expandedRows.has(log.id)
                  return (
                    <>
                      <TableRow
                        key={log.id}
                        className="cursor-pointer hover:bg-muted/50"
                        onClick={() => toggleRow(log.id)}
                      >
                        <TableCell className="font-mono text-xs">
                          {formatDate(log.timestamp)}
                        </TableCell>
                        <TableCell>
                          {log.userId ? (
                            <Link
                              href={`/admin/members/${log.userId}`}
                              className="group block"
                              onClick={(e) => e.stopPropagation()}
                            >
                              <p className="font-medium text-sm group-hover:text-primary group-hover:underline">
                                {log.user?.name || 'System'}
                              </p>
                              <p className="text-xs text-muted-foreground">
                                {log.user?.email}
                              </p>
                            </Link>
                          ) : (
                            <div>
                              <p className="font-medium text-sm">System</p>
                            </div>
                          )}
                        </TableCell>
                        <TableCell>
                          <Badge
                            variant={actionColors[log.action] || 'secondary'}
                          >
                            {log.action.replace(/_/g, ' ')}
                          </Badge>
                        </TableCell>
                        <TableCell>
                          <div>
                            <p className="text-sm">{log.entityType}</p>
                            {log.entityId && (() => {
                              const link = getEntityLink(log.entityType, log.entityId)
                              return link ? (
                                <Link
                                  href={link}
                                  className="text-xs text-primary font-mono hover:underline"
                                  onClick={(e) => e.stopPropagation()}
                                >
                                  {log.entityId.slice(0, 8)}...
                                </Link>
                              ) : (
                                <p className="text-xs text-muted-foreground font-mono">
                                  {log.entityId.slice(0, 8)}...
                                </p>
                              )
                            })()}
                          </div>
                        </TableCell>
                        <TableCell className="font-mono text-xs">
                          {log.ipAddress || '-'}
                        </TableCell>
                        <TableCell>
                          {isExpanded ? (
                            <ChevronUp className="h-4 w-4" />
                          ) : (
                            <ChevronDown className="h-4 w-4" />
                          )}
                        </TableCell>
                      </TableRow>
                      {isExpanded && (
                        <TableRow key={`${log.id}-details`}>
                          <TableCell colSpan={6} className="bg-muted/30">
                            <div className="p-4 space-y-2">
                              <div className="grid gap-4 sm:grid-cols-2">
                                <div>
                                  <p className="text-xs font-medium text-muted-foreground">
                                    Entity ID
                                  </p>
                                  {log.entityId ? (() => {
                                    const link = getEntityLink(log.entityType, log.entityId)
                                    return link ? (
                                      <Link href={link} className="font-mono text-sm text-primary hover:underline" onClick={(e) => e.stopPropagation()}>
                                        {log.entityId}
                                      </Link>
                                    ) : (
                                      <p className="font-mono text-sm">{log.entityId}</p>
                                    )
                                  })() : (
                                    <p className="font-mono text-sm">N/A</p>
                                  )}
                                </div>
                                <div>
                                  <p className="text-xs font-medium text-muted-foreground">
                                    User Agent
                                  </p>
                                  <p className="text-sm truncate max-w-md">
                                    {log.userAgent || 'N/A'}
                                  </p>
                                </div>
                              </div>
                              {log.detailsJson && (
                                <div>
                                  <p className="text-xs font-medium text-muted-foreground mb-1">
                                    Details
                                  </p>
                                  {log.action === 'JUROR_DROPOUT_RESHUFFLE' ? (
                                    <ReshuffleDetailView details={log.detailsJson as Record<string, unknown>} />
                                  ) : log.action === 'COI_REASSIGNMENT' ? (
                                    <COIReassignmentDetailView details={log.detailsJson as Record<string, unknown>} />
                                  ) : (
                                    <pre className="text-xs bg-muted rounded p-2 overflow-x-auto">
                                      {JSON.stringify(log.detailsJson, null, 2)}
                                    </pre>
                                  )}
                                </div>
                              )}
                              {!!(log as Record<string, unknown>).previousDataJson && (
                                <div>
                                  <p className="text-xs font-medium text-muted-foreground mb-1 flex items-center gap-1">
                                    <ArrowLeftRight className="h-3 w-3" />
                                    Changes (Before / After)
                                  </p>
                                  <DiffViewer
                                    before={(log as Record<string, unknown>).previousDataJson}
                                    after={log.detailsJson}
                                  />
                                </div>
                              )}
                              {groupBySession && !!(log as Record<string, unknown>).sessionId && (
                                <div>
                                  <p className="text-xs font-medium text-muted-foreground">
                                    Session ID
                                  </p>
                                  <p className="font-mono text-xs">
                                    {String((log as Record<string, unknown>).sessionId)}
                                  </p>
                                </div>
                              )}
                            </div>
                          </TableCell>
                        </TableRow>
                      )}
                    </>
                  )
                })}
              </TableBody>
            </Table>
          </Card>

          {/* Mobile Card View */}
          <div className="space-y-4 md:hidden">
            {data.logs.map((log) => {
              const isExpanded = expandedRows.has(log.id)
              return (
                <Card
                  key={log.id}
                  className="cursor-pointer"
                  onClick={() => toggleRow(log.id)}
                >
                  <CardHeader className="pb-2">
                    <div className="flex items-start justify-between">
                      <div className="flex items-center gap-2">
                        <Badge
                          variant={actionColors[log.action] || 'secondary'}
                        >
                          {log.action.replace(/_/g, ' ')}
                        </Badge>
                        <span className="text-sm text-muted-foreground">
                          {log.entityType}
                        </span>
                      </div>
                      {isExpanded ? (
                        <ChevronUp className="h-4 w-4" />
                      ) : (
                        <ChevronDown className="h-4 w-4" />
                      )}
                    </div>
                  </CardHeader>
                  <CardContent className="space-y-2">
                    <div className="flex items-center gap-4 text-sm">
                      <div className="flex items-center gap-1 text-muted-foreground">
                        <Clock className="h-3 w-3" />
                        <span className="text-xs">
                          {formatDate(log.timestamp)}
                        </span>
                      </div>
                      {log.userId ? (
                        <Link
                          href={`/admin/members/${log.userId}`}
                          className="flex items-center gap-1 text-muted-foreground hover:text-primary"
                          onClick={(e) => e.stopPropagation()}
                        >
                          <User className="h-3 w-3" />
                          <span className="text-xs hover:underline">
                            {log.user?.name || 'System'}
                          </span>
                        </Link>
                      ) : (
                        <div className="flex items-center gap-1 text-muted-foreground">
                          <User className="h-3 w-3" />
                          <span className="text-xs">System</span>
                        </div>
                      )}
                    </div>

                    {isExpanded && (
                      <div className="mt-4 pt-4 border-t space-y-3">
                        <div>
                          <p className="text-xs font-medium text-muted-foreground">
                            Entity ID
                          </p>
                          <p className="font-mono text-xs">
                            {log.entityId || 'N/A'}
                          </p>
                        </div>
                        <div>
                          <p className="text-xs font-medium text-muted-foreground">
                            IP Address
                          </p>
                          <p className="font-mono text-xs">
                            {log.ipAddress || 'N/A'}
                          </p>
                        </div>
                        {log.detailsJson && (
                          <div>
                            <p className="text-xs font-medium text-muted-foreground mb-1">
                              Details
                            </p>
                            {log.action === 'JUROR_DROPOUT_RESHUFFLE' ? (
                              <ReshuffleDetailView details={log.detailsJson as Record<string, unknown>} />
                            ) : log.action === 'COI_REASSIGNMENT' ? (
                              <COIReassignmentDetailView details={log.detailsJson as Record<string, unknown>} />
                            ) : (
                              <pre className="text-xs bg-muted rounded p-2 overflow-x-auto">
                                {JSON.stringify(log.detailsJson, null, 2)}
                              </pre>
                            )}
                          </div>
                        )}
                      </div>
                    )}
                  </CardContent>
                </Card>
              )
            })}
          </div>

          {/* Pagination */}
          <div className="flex items-center justify-between">
            <p className="text-sm text-muted-foreground">
              Showing {(page - 1) * 50 + 1} to{' '}
              {Math.min(page * 50, data.total)} of {data.total} results
            </p>
            <div className="flex items-center gap-2">
              <Button
                variant="outline"
                size="sm"
                onClick={() => setPage(page - 1)}
                disabled={page === 1}
              >
                <ChevronLeft className="h-4 w-4" />
                Previous
              </Button>
              <span className="text-sm">
                Page {page} of {data.totalPages}
              </span>
              <Button
                variant="outline"
                size="sm"
                onClick={() => setPage(page + 1)}
                disabled={page >= data.totalPages}
              >
                Next
                <ChevronRight className="h-4 w-4" />
              </Button>
            </div>
          </div>
        </>
      ) : (
        <Card>
          <CardContent className="flex flex-col items-center justify-center py-12 text-center">
            <Activity className="h-12 w-12 text-muted-foreground/50" />
            <p className="mt-2 font-medium">No audit logs found</p>
            <p className="text-sm text-muted-foreground">
              {hasFilters
                ? 'Try adjusting your filters'
                : 'Activity will appear here as users interact with the system'}
            </p>
          </CardContent>
        </Card>
      )}

      {/* CSV Export Dialog with Column Selection */}
      <CsvExportDialog
        open={showExportDialog}
        onOpenChange={setShowExportDialog}
        exportData={exportLogs.data ?? undefined}
        isLoading={exportLogs.isFetching}
        filename="audit-logs"
        onRequestData={handleRequestExportData}
      />
    </div>
  )
}

function ReshuffleDetailView({ details }: { details: Record<string, unknown> }) {
  const reassignedTo = (details.reassignedTo ?? {}) as Record<string, number>
  const jurorIds = Object.keys(reassignedTo)
  const moves = (details.moves ?? []) as { projectId: string; projectTitle: string; newJurorId: string; newJurorName: string }[]

  // Resolve juror IDs to names
  const { data: nameMap } = trpc.user.resolveNames.useQuery(
    { ids: [...jurorIds, details.droppedJurorId as string].filter(Boolean) },
    { enabled: jurorIds.length > 0 },
  )

  const droppedName = (details.droppedJurorName as string) || (nameMap && details.droppedJurorId ? nameMap[details.droppedJurorId as string] : null) || (details.droppedJurorId as string)

  return (
    <div className="rounded-lg border bg-white overflow-hidden text-sm">
      {/* Summary */}
      <div className="p-3 bg-muted/50 border-b space-y-1">
        <div className="flex items-center gap-2">
          <Badge variant="destructive">Juror Dropout</Badge>
          <span className="font-semibold">{droppedName}</span>
        </div>
        <p className="text-xs text-muted-foreground">
          {String(details.movedCount)} project(s) reassigned, {String(details.failedCount)} failed
          {details.removedFromGroup ? ' — removed from jury group' : ''}
        </p>
      </div>

      {/* Per-project moves (new format) */}
      {moves.length > 0 && (
        <div className="p-3">
          <p className="text-xs font-medium text-muted-foreground mb-2">Project → New Juror</p>
          <table className="w-full text-xs">
            <thead>
              <tr className="text-muted-foreground border-b">
                <th className="text-left py-1 font-medium">Project</th>
                <th className="text-left py-1 font-medium">Reassigned To</th>
              </tr>
            </thead>
            <tbody>
              {moves.map((move, i) => (
                <tr key={i} className="border-b last:border-0">
                  <td className="py-1.5 pr-2">{move.projectTitle}</td>
                  <td className="py-1.5 font-medium">{move.newJurorName}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {/* Fallback: count-based view (old format, no per-project detail) */}
      {moves.length === 0 && jurorIds.length > 0 && (
        <div className="p-3">
          <p className="text-xs font-medium text-muted-foreground mb-2">Reassignment Summary (project detail not available)</p>
          <table className="w-full text-xs">
            <thead>
              <tr className="text-muted-foreground border-b">
                <th className="text-left py-1 font-medium">Juror</th>
                <th className="text-right py-1 font-medium">Projects Received</th>
              </tr>
            </thead>
            <tbody>
              {jurorIds.map((id) => (
                <tr key={id} className="border-b last:border-0">
                  <td className="py-1.5">{nameMap?.[id] || id}</td>
                  <td className="py-1.5 text-right font-medium">{reassignedTo[id]}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {/* Failed projects */}
      {Array.isArray(details.failedProjects) && (details.failedProjects as string[]).length > 0 && (
        <div className="p-3 border-t bg-red-50/50">
          <p className="text-xs font-medium text-red-700 mb-1">Could not reassign:</p>
          <ul className="text-xs text-muted-foreground list-disc list-inside">
            {(details.failedProjects as string[]).map((p, i) => (
              <li key={i}>{p}</li>
            ))}
          </ul>
        </div>
      )}
    </div>
  )
}

function COIReassignmentDetailView({ details }: { details: Record<string, unknown> }) {
  const ids = [details.oldJurorId, details.newJurorId].filter(Boolean) as string[]
  const { data: nameMap } = trpc.user.resolveNames.useQuery(
    { ids },
    { enabled: ids.length > 0 },
  )

  const oldName = nameMap?.[details.oldJurorId as string] || (details.oldJurorId as string)
  const newName = nameMap?.[details.newJurorId as string] || (details.newJurorId as string)

  return (
    <div className="rounded-lg border bg-white overflow-hidden text-sm">
      <div className="p-3 space-y-2">
        <div className="flex items-center gap-2">
          <Badge variant="secondary">COI Reassignment</Badge>
        </div>
        <div className="grid grid-cols-2 gap-4 text-xs">
          <div>
            <p className="text-muted-foreground">From</p>
            <p className="font-medium">{oldName}</p>
          </div>
          <div>
            <p className="text-muted-foreground">To</p>
            <p className="font-medium">{newName}</p>
          </div>
        </div>
        <div className="text-xs text-muted-foreground">
          Project: <span className="font-mono">{(details.projectId as string)?.slice(0, 12)}...</span>
          {' | '}Round: <span className="font-mono">{(details.roundId as string)?.slice(0, 12)}...</span>
        </div>
      </div>
    </div>
  )
}

function DiffViewer({ before, after }: { before: unknown; after: unknown }) {
  const beforeObj = typeof before === 'object' && before !== null ? before as Record<string, unknown> : {}
  const afterObj = typeof after === 'object' && after !== null ? after as Record<string, unknown> : {}
  const allKeys = Array.from(new Set([...Object.keys(beforeObj), ...Object.keys(afterObj)]))
  const changedKeys = allKeys.filter(
    (key) => JSON.stringify(beforeObj[key]) !== JSON.stringify(afterObj[key])
  )

  if (changedKeys.length === 0) {
    return (
      <p className="text-xs text-muted-foreground italic">No differences detected</p>
    )
  }

  return (
    <div className="rounded-lg border overflow-hidden text-xs font-mono">
      <div className="grid grid-cols-3 bg-muted p-2 font-medium">
        <span>Field</span>
        <span>Before</span>
        <span>After</span>
      </div>
      {changedKeys.map((key) => (
        <div key={key} className="grid grid-cols-3 p-2 border-t">
          <span className="font-medium text-muted-foreground">{key}</span>
          <span className="text-red-600 break-all">
            {beforeObj[key] !== undefined ? JSON.stringify(beforeObj[key]) : '--'}
          </span>
          <span className="text-green-600 break-all">
            {afterObj[key] !== undefined ? JSON.stringify(afterObj[key]) : '--'}
          </span>
        </div>
      ))}
    </div>
  )
}

function AuditLogSkeleton() {
  return (
    <Card>
      <CardContent className="p-6">
        <div className="space-y-4">
          {[...Array(10)].map((_, i) => (
            <div key={i} className="flex items-center gap-4">
              <Skeleton className="h-4 w-32" />
              <Skeleton className="h-4 w-24" />
              <Skeleton className="h-6 w-20" />
              <Skeleton className="h-4 w-16" />
              <Skeleton className="h-4 w-24 ml-auto" />
            </div>
          ))}
        </div>
      </CardContent>
    </Card>
  )
}
