'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'

// Action type options
const ACTION_TYPES = [
  '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_DOWNLOADED',
  'BULK_CREATE',
  'BULK_UPDATE_STATUS',
  'UPDATE_EVALUATION_FORM',
  'ROLE_CHANGED',
  'PASSWORD_SET',
  'PASSWORD_CHANGED',
]

// Entity type options
const ENTITY_TYPES = [
  'User',
  'Program',
  'Round',
  'Project',
  'Assignment',
  'Evaluation',
  'EvaluationForm',
  'ProjectFile',
  'GracePeriod',
]

// 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_DOWNLOADED: 'outline',
  ROLE_CHANGED: 'secondary',
  PASSWORD_SET: 'outline',
  PASSWORD_CHANGED: 'outline',
}

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)

  // 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>
                          <div>
                            <p className="font-medium text-sm">
                              {log.user?.name || 'System'}
                            </p>
                            <p className="text-xs text-muted-foreground">
                              {log.user?.email}
                            </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 && (
                              <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>
                                  <p className="font-mono text-sm">
                                    {log.entityId || '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>
                                  <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>
                      <div className="flex items-center gap-1 text-muted-foreground">
                        <User className="h-3 w-3" />
                        <span className="text-xs">
                          {log.user?.name || '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>
                            <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 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>
  )
}
