T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/backups/lavocat.quebec/backup-20250730-021618/src/pages/admin/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/backups/lavocat.quebec/backup-20250730-021618/src/pages/admin/index.tsx
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { useSession } from 'next-auth/react';
import dynamic from 'next/dynamic';
import type { Registration } from '@prisma/client';
import { format } from 'date-fns';
import Link from 'next/link';
import RegistrationForm from '@/components/RegistrationForm';
import { motion, AnimatePresence } from 'framer-motion';
import { getFacilityName } from '@/utils/facilities';
import { canAccessAdmin } from '@/lib/auth-utils';
import { useMemo } from 'react';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, BarChart, Bar, LabelList } from 'recharts';
import jsPDF from 'jspdf';
import 'jspdf-autotable';

const DATE_RANGES = [
  { value: '24h', label: 'Last 24h' },
  { value: '7d', label: 'Last 7 days' },
  { value: '30d', label: 'Last 30 days' },
  { value: '90d', label: 'Last 90 days' },
  { value: 'custom', label: 'Custom Range' }
];

const USER_TYPES = [
  { value: 'all', label: 'All Users' },
  { value: 'admin', label: 'Admin' },
  { value: 'lawyer', label: 'Lawyer' },
  { value: 'client', label: 'Client' },
  { value: 'judge', label: 'Judge' },
  { value: 'jurist', label: 'Jurist' },
  { value: 'mediator', label: 'Mediator' },
  { value: 'business', label: 'Business' },
  { value: 'guest', label: 'Guest' }
];

const DEVICE_TYPES = [
  { value: 'all', label: 'All Devices' },
  { value: 'desktop', label: 'Desktop' },
  { value: 'mobile', label: 'Mobile' },
  { value: 'tablet', label: 'Tablet' }
];

const SEARCH_TYPES = [
  { value: 'all', label: 'All Types' },
  { value: 'users', label: 'Users' },
  { value: 'cases', label: 'Cases' },
  { value: 'documents', label: 'Documents' },
  { value: 'businesses', label: 'Businesses' }
];

const REGIONS = [
  { value: 'all', label: 'All Regions' },
  { value: 'quebec', label: 'Quebec' },
  { value: 'ontario', label: 'Ontario' },
  { value: 'british_columbia', label: 'British Columbia' },
  { value: 'alberta', label: 'Alberta' },
  { value: 'federal', label: 'Federal' },
  { value: 'international', label: 'International' }
];

const PrivateChat = dynamic(() => import('@/components/Chat/PrivateChat'), { ssr: false });

// Dynamically import LayoutWithSidebar with no SSR
const LayoutWithSidebar = dynamic(() => import('@/components/LayoutWithSidebar'), {
  ssr: false
});

interface RegistrationWithDetails extends Registration {
  address: {
    street: string;
    city: string;
    state: string;
    postalCode: string;
    country: string;
  } | null;
  detaineeInfo: {
    name: string;
    facility: string;
    inmateId: string;
    incarcerationDate: string;
    expectedReleaseDate?: string | null;
  } | null;
  documents?: { id: string; name: string; url: string }[];
}

const translations = {
  en: {
    dashboard: 'Admin Dashboard',
    manage: 'Manage class action applications here.',
    stats: {
      total: 'Total Applications',
      pending: 'Pending',
      approved: 'Approved',
      rejected: 'Rejected',
    },
    manageUsers: 'Manage Users',
    newApplication: 'Create New Application',
    noApplications: 'No applications found.',
    searchPlaceholder: 'Search by name or email...',
    allStatuses: 'All Statuses',
    status: {
      all: 'All Statuses',
      pending: 'Pending',
      approved: 'Approved',
      rejected: 'Rejected',
    },
    bulk: {
      approve: 'Approve',
      reject: 'Reject',
      delete: 'Delete',
    },
    table: {
      date: 'Date',
      name: 'Name',
      detainee: 'Detainee',
      status: 'Status',
      actions: 'Actions',
    },
    confirmDelete: 'Are you sure you want to delete this application?',
    errorDelete: 'Error deleting application',
    errorLoad: 'Error loading applications',
    errorRefresh: 'Error refreshing registrations',
    document: {
      add: 'Add Document',
      uploading: 'Uploading...',
      uploadError: 'Error uploading document',
      delete: 'Delete Document',
      deleteConfirm: 'Are you sure you want to delete this document?',
      deleteError: 'Error deleting document',
      documents: 'Documents',
    },
    modal: {
      newApplication: 'New Application',
      close: 'Close',
    },
    fileTooLarge: 'File is too large (max 100MB)',
    unsupportedFile: 'Unsupported file type',
    approve: 'Approve',
    reject: 'Reject',
    delete: 'Delete',
    actions: 'Actions',
    loading: 'Loading...',
    restore: {
      title: 'Restore Backup',
      description: 'Upload a backup file to restore the system to a previous state.',
      button: 'Restore Backup',
      upload: 'Upload Backup File',
      success: 'Restore completed successfully',
      error: 'Restore failed',
      close: 'Close',
      loading: 'Restoring...',
    },
  },
  fr: {
    dashboard: 'Tableau de Bord Administrateur',
    manage: 'Gérez les demandes d\'action collective ici.',
    stats: {
      total: 'Total des demandes',
      pending: 'En attente',
      approved: 'Approuvées',
      rejected: 'Rejetées',
    },
    manageUsers: 'Gérer les utilisateurs',
    newApplication: 'Créer une nouvelle demande',
    noApplications: 'Aucune demande trouvée.',
    searchPlaceholder: 'Rechercher par nom ou email...',
    allStatuses: 'Tous les statuts',
    status: {
      all: 'Tous les statuts',
      pending: 'En attente',
      approved: 'Approuvé',
      rejected: 'Rejeté',
    },
    bulk: {
      approve: 'Approuver',
      reject: 'Rejeter',
      delete: 'Supprimer',
    },
    table: {
      date: 'Date',
      name: 'Nom',
      detainee: 'Détenu',
      status: 'Statut',
      actions: 'Actions',
    },
    confirmDelete: 'Êtes-vous sûr de vouloir supprimer cette demande ?',
    errorDelete: 'Erreur lors de la suppression de la demande',
    errorLoad: 'Erreur lors du chargement des demandes',
    errorRefresh: 'Erreur lors du rafraîchissement des demandes',
    document: {
      add: 'Ajouter un document',
      uploading: 'Téléchargement...',
      uploadError: 'Erreur lors du téléchargement du document',
      delete: 'Supprimer le document',
      deleteConfirm: 'Êtes-vous sûr de vouloir supprimer ce document ?',
      deleteError: 'Erreur lors de la suppression du document',
      documents: 'Documents',
    },
    modal: {
      newApplication: 'Nouvelle demande',
      close: 'Fermer',
    },
    fileTooLarge: 'Le fichier est trop volumineux (max 100MB)',
    unsupportedFile: 'Type de fichier non supporté',
    approve: 'Approuver',
    reject: 'Rejeter',
    delete: 'Supprimer',
    actions: 'Actions',
    loading: 'Chargement...',
    restore: {
      title: 'Restaurer la Sauvegarde',
      description: 'Téléchargez un fichier de sauvegarde pour restaurer le système à un état précédent.',
      button: 'Restaurer la Sauvegarde',
      upload: 'Télécharger le Fichier de Sauvegarde',
      success: 'Restauration terminée avec succès',
      error: 'Restauration échouée',
      close: 'Fermer',
      loading: 'Restauration...',
    },
  }
};

const getStatusColor = (status: string) => {
  switch (status) {
    case 'APPROVED':
    case 'COMPLETED':
    case 'PAYMENT_RECEIVED':
      return 'bg-green-100 text-green-800';
    case 'REJECTED':
    case 'DOCUMENTS_EXPIRED':
    case 'INFORMATION_MISMATCH':
    case 'ESCALATED':
      return 'bg-red-100 text-red-800';
    case 'PENDING':
    case 'ADDITIONAL_INFO_NEEDED':
    case 'PENDING_PAYMENT':
      return 'bg-yellow-100 text-yellow-800';
    case 'MISSING_DOCUMENTS':
    case 'DOCUMENTS_INCOMPLETE':
      return 'bg-orange-100 text-orange-800';
    case 'DOCUMENTS_UNDER_REVIEW':
    case 'PENDING_LAWYER_APPROVAL':
    case 'PENDING_FACILITY_APPROVAL':
      return 'bg-blue-100 text-blue-800';
    case 'VERIFICATION_IN_PROGRESS':
    case 'FINAL_REVIEW':
      return 'bg-purple-100 text-purple-800';
    case 'ON_HOLD':
      return 'bg-gray-100 text-gray-800';
    case 'WebAd':
      return 'bg-pink-100 text-pink-800';
    default:
      return 'bg-yellow-100 text-yellow-800';
  }
};

function exportCSV(data: any[], headers: string[], filename: string) {
  const csvRows = [headers.join(',')];
  for (const row of data) {
    csvRows.push(headers.map(h => JSON.stringify(row[h] ?? '')).join(','));
  }
  const blob = new Blob([csvRows.join('\n')], { type: 'text/csv' });
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  window.URL.revokeObjectURL(url);
}

function exportExcel(data: any[], headers: string[], filename: string) {
  // Simple Excel export using CSV format (Excel opens CSV)
  exportCSV(data, headers, filename.endsWith('.csv') ? filename : filename + '.csv');
}

function exportPDF(title: string, data: any[], headers: string[], filename: string) {
  const doc = new jsPDF();
  doc.text(title, 14, 16);
  (doc as any).autoTable({
    head: [headers],
    body: data.map(row => headers.map(h => row[h] ?? '')),
    startY: 22,
    styles: { fontSize: 9 },
    headStyles: { fillColor: [99, 102, 241] }
  });
  doc.save(filename);
}

export default function AdminDashboard() {
  const { data: session, status } = useSession();
  const router = useRouter();
  const { locale } = router;
  const [registrations, setRegistrations] = useState<RegistrationWithDetails[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [search, setSearch] = useState('');
  const [statusFilter, setStatusFilter] = useState('ALL');
  const [selectedIds, setSelectedIds] = useState<string[]>([]);
  const [bulkActionLoading, setBulkActionLoading] = useState(false);
  const [stats, setStats] = useState({
    total: 0,
    pending: 0,
    approved: 0,
    rejected: 0,
  });
  const [isNewApplicationModalOpen, setIsNewApplicationModalOpen] = useState(false);
  const [isDeleting, setIsDeleting] = useState<string | null>(null);
  const [isUpdatingStatus, setIsUpdatingStatus] = useState<string | null>(null);
  const [isUploading, setIsUploading] = useState(false);
  const [uploadError, setUploadError] = useState('');
  const [previewDoc, setPreviewDoc] = useState<{ url: string; name: string } | null>(null);
  const [isRestoreModalOpen, setIsRestoreModalOpen] = useState(false);
  const [restoreFile, setRestoreFile] = useState<File | null>(null);
  const [isRestoring, setIsRestoring] = useState(false);
  const [restoreError, setRestoreError] = useState<string | null>(null);
  const [restoreSuccess, setRestoreSuccess] = useState(false);
  const [openChatId, setOpenChatId] = useState<string | null>(null);
  const [showPrivateChat, setShowPrivateChat] = useState<{ open: boolean; registrationId: string | null }>({ open: false, registrationId: null });
  const t = translations[locale as 'en' | 'fr'] || translations.en;
  const [isMobile, setIsMobile] = useState(false);
  const [searchAnalytics, setSearchAnalytics] = useState<any>(null);
  const [searchAnalyticsLoading, setSearchAnalyticsLoading] = useState(true);
  const [searchAnalyticsError, setSearchAnalyticsError] = useState('');
  const [analyticsDateRange, setAnalyticsDateRange] = useState('7d');
  const [analyticsUserType, setAnalyticsUserType] = useState('all');
  const [customStartDate, setCustomStartDate] = useState('');
  const [customEndDate, setCustomEndDate] = useState('');
  const [analyticsDeviceType, setAnalyticsDeviceType] = useState('all');
  const [analyticsSearchType, setAnalyticsSearchType] = useState('all');
  const [analyticsRegion, setAnalyticsRegion] = useState('all');
  const [analyticsOrganization, setAnalyticsOrganization] = useState('all');

  // Mobile detection
  useEffect(() => {
    const checkMobile = () => {
      setIsMobile(window.innerWidth < 768);
    };
    
    checkMobile();
    window.addEventListener('resize', checkMobile);
    return () => window.removeEventListener('resize', checkMobile);
  }, []);

  const getStatusLabel = (status: string) => {
    const statusMap: { [key: string]: { en: string; fr: string } } = {
      PENDING: { en: 'Pending', fr: 'En attente' },
      MISSING_DOCUMENTS: { en: 'Missing Documents', fr: 'Documents manquants' },
      DOCUMENTS_UNDER_REVIEW: { en: 'Documents Under Review', fr: 'Documents en cours d\'examen' },
      ADDITIONAL_INFO_NEEDED: { en: 'Additional Info Needed', fr: 'Informations supplémentaires requises' },
      VERIFICATION_IN_PROGRESS: { en: 'Verification In Progress', fr: 'Vérification en cours' },
      LAWYER_VERIFICATION: { en: 'Lawyer Verification', fr: 'Vérification par l\'avocat' },
      FACILITY_VERIFICATION: { en: 'Facility Verification', fr: 'Vérification par l\'établissement' },
      DOCUMENTS_EXPIRED: { en: 'Documents Expired', fr: 'Documents expirés' },
      DOCUMENTS_INCOMPLETE: { en: 'Documents Incomplete', fr: 'Documents incomplets' },
      INFORMATION_MISMATCH: { en: 'Information Mismatch', fr: 'Incohérence d\'informations' },
      PENDING_PAYMENT: { en: 'Pending Payment', fr: 'Paiement en attente' },
      PAYMENT_RECEIVED: { en: 'Payment Received', fr: 'Paiement reçu' },
      PENDING_LAWYER_APPROVAL: { en: 'Pending Lawyer Approval', fr: 'En attente d\'approbation par l\'avocat' },
      PENDING_FACILITY_APPROVAL: { en: 'Pending Facility Approval', fr: 'En attente d\'approbation par l\'établissement' },
      ON_HOLD: { en: 'On Hold', fr: 'En pause' },
      ESCALATED: { en: 'Escalated', fr: 'Escaladé' },
      FINAL_REVIEW: { en: 'Final Review', fr: 'Examen final' },
      APPROVED: { en: 'Approved', fr: 'Approuvée' },
      REJECTED: { en: 'Rejected', fr: 'Rejetée' },
      COMPLETED: { en: 'Completed', fr: 'Terminé' },
      WebAd: { en: 'Web Ad', fr: 'Web Ad' }
    };
    return statusMap[status]?.[locale as 'en' | 'fr'] || status;
  };

  const StatusIcon = ({ status }: { status: string }) => {
    const iconMap: { [key: string]: JSX.Element } = {
      APPROVED: <span className="text-green-500 text-2xl">✔️</span>,
      REJECTED: <span className="text-red-500 text-2xl">❌</span>,
      PENDING: <span className="text-yellow-500 text-2xl">⏳</span>,
      DOCUMENTS_UNDER_REVIEW: <span className="text-blue-500 text-2xl">📄</span>,
      MISSING_DOCUMENTS: <span className="text-orange-500 text-2xl">📄</span>,
      PENDING_FACILITY_APPROVAL: <span className="text-blue-400 text-2xl">🏢</span>,
      // ...add more as needed
    };
    return iconMap[status] || <span className="text-gray-400 text-2xl">📝</span>;
  };

  const handleViewAndNavigate = (id: string) => {
    router.push(`/admin/registrations/${id}`);
  };

  const handleDeleteApplication = async (id: string) => {
    if (!window.confirm(t.confirmDelete)) {
      return;
    }

    setIsDeleting(id);
    try {
      const response = await fetch(`/api/admin/registrations/${id}`, {
        method: 'DELETE',
      });

      if (!response.ok) {
        throw new Error(t.errorDelete);
      }

      setRegistrations(prev => {
        const updated = prev.filter(reg => reg.id !== id);
        setStats({
          total: updated.length,
          pending: updated.filter(reg => reg.status === 'PENDING').length,
          approved: updated.filter(reg => reg.status === 'APPROVED').length,
          rejected: updated.filter(reg => reg.status === 'REJECTED').length,
        });
        return updated;
      });
    } catch (err) {
      console.error('Error deleting application:', err);
      setError(t.errorDelete);
    } finally {
      setIsDeleting(null);
    }
  };

  useEffect(() => {
    if (status === 'loading') return;
    
    if (!session) {
      router.push('/auth/login');
      return;
    }

    if (!canAccessAdmin(session)) {
      console.log('User role:', session.user.role, 'redirecting to user dashboard');
      router.push('/user/dashboard');
      return;
    }
  }, [session, status, router]);

  useEffect(() => {
    const fetchData = async () => {
      console.log('Admin Dashboard - Status:', status);
      console.log('Admin Dashboard - Session:', session);
      console.log('Admin Dashboard - User Role:', session?.user?.role);
      
      if (status !== 'authenticated' || !canAccessAdmin(session)) {
        console.log('Admin Dashboard - Not authenticated or not admin, returning');
        return;
      }

      try {
        console.log('Admin Dashboard - Fetching registrations...');
        const response = await fetch('/api/admin/registrations');
        console.log('Admin Dashboard - Response status:', response.status);
        
        if (!response.ok) {
          const errorData = await response.json();
          console.log('Admin Dashboard - Error data:', errorData);
          throw new Error(errorData.message || 'Failed to fetch registrations');
        }
        const data = await response.json();
        setRegistrations(data);

        // Calculate stats
        const stats = {
          total: data.length,
          pending: data.filter((reg: RegistrationWithDetails) => reg.status === 'PENDING').length,
          approved: data.filter((reg: RegistrationWithDetails) => reg.status === 'APPROVED').length,
          rejected: data.filter((reg: RegistrationWithDetails) => reg.status === 'REJECTED').length,
        };
        setStats(stats);
      } catch (err: any) {
        setError(err.message || 'Error loading data');
        console.error('Error:', err);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [status, session]);

  useEffect(() => {
    // Fetch search analytics
    const fetchAnalytics = async () => {
      setSearchAnalyticsLoading(true);
      try {
        const params = new URLSearchParams({
          type: 'overview',
          userType: analyticsUserType,
          deviceType: analyticsDeviceType,
          searchType: analyticsSearchType,
          region: analyticsRegion,
          organization: analyticsOrganization
        });
        if (analyticsDateRange === 'custom' && customStartDate && customEndDate) {
          params.set('startDate', customStartDate);
          params.set('endDate', customEndDate);
        } else {
          params.set('period', analyticsDateRange);
        }
        const res = await fetch(`/api/search/analytics?${params}`);
        if (!res.ok) throw new Error('Failed to fetch search analytics');
        const data = await res.json();
        setSearchAnalytics(data);
      } catch (err: any) {
        setSearchAnalyticsError(err.message || 'Error loading analytics');
      } finally {
        setSearchAnalyticsLoading(false);
      }
    };
    if (analyticsDateRange !== 'custom' || (customStartDate && customEndDate)) {
      fetchAnalytics();
    }
  }, [analyticsDateRange, analyticsUserType, analyticsDeviceType, analyticsSearchType, analyticsRegion, analyticsOrganization, customStartDate, customEndDate]);

  // Filtering and search
  const filtered = registrations.filter((r) => {
    const matchesSearch =
      r.firstName.toLowerCase().includes(search.toLowerCase()) ||
      r.lastName.toLowerCase().includes(search.toLowerCase()) ||
      r.email.toLowerCase().includes(search.toLowerCase());
    const matchesStatus =
      statusFilter === 'ALL' || r.status === statusFilter;
    return matchesSearch && matchesStatus;
  });

  // Bulk actions
  const handleBulkAction = async (action: 'APPROVED' | 'REJECTED' | 'DELETE') => {
    setBulkActionLoading(true);
    try {
      if (action === 'DELETE') {
        await Promise.all(selectedIds.map(async (id) => {
          await fetch(`/api/admin/registrations/${id}`, { method: 'DELETE' });
        }));
        setRegistrations((prev) => {
          const updated = prev.filter((r) => !selectedIds.includes(r.id));
          setStats({
            total: updated.length,
            pending: updated.filter((r) => r.status === 'PENDING').length,
            approved: updated.filter((r) => r.status === 'APPROVED').length,
            rejected: updated.filter((r) => r.status === 'REJECTED').length,
          });
          return updated;
        });
      } else {
        await Promise.all(selectedIds.map(async (id) => {
          await fetch(`/api/admin/registrations/${id}`, {
            method: 'PATCH',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ status: action }),
          });
        }));
        setRegistrations((prev) =>
          prev.map((r) =>
            selectedIds.includes(r.id) ? { ...r, status: action } : r
          )
        );
      }
      setSelectedIds([]);
      // Update stats
      setStats({
        total: registrations.length,
        pending: registrations.filter((r) => r.status === 'PENDING').length,
        approved: registrations.filter((r) => r.status === 'APPROVED').length,
        rejected: registrations.filter((r) => r.status === 'REJECTED').length,
      });
    } catch (err) {
      setError('Bulk action failed');
    } finally {
      setBulkActionLoading(false);
    }
  };

  const toggleSelect = (id: string) => {
    setSelectedIds((prev) =>
      prev.includes(id) ? prev.filter((sid) => sid !== id) : [...prev, id]
    );
  };

  const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>, registrationId: string) => {
    const file = event.target.files?.[0];
    if (!file) return;

    // Validate file size (max 100MB)
    if (file.size > 100 * 1024 * 1024) {
      setUploadError(t.fileTooLarge);
      return;
    }

    // Validate file type
    const allowedTypes = [
      'application/pdf',
      'image/jpeg',
      'image/png',
      'video/mp4',
      'video/mpeg',
      'video/x-mpeg',
      'video/x-mpeg4',
      'video/webm',
      'video/quicktime', // mov
      'video/x-msvideo', // avi
      'video/x-m4v', // m4v
      'video/3gpp', // 3gp
      'video/x-flv', // flv
      'video/x-matroska', // mkv
      'video/x-ms-wmv' // wmv
    ];
    if (!allowedTypes.includes(file.type)) {
      setUploadError(t.unsupportedFile);
      return;
    }

    setIsUploading(true);
    setUploadError('');

    try {
      const formData = new FormData();
      formData.append('file', file);

      // For new registrations, we'll just preview the file
      if (registrationId === 'new') {
        const objectUrl = URL.createObjectURL(file);
        setPreviewDoc({ url: objectUrl, name: file.name });
        return;
      }

      const uploadResponse = await fetch(`/api/admin/registrations/${registrationId}/documents`, {
        method: 'POST',
        body: formData,
      });

      const contentType = uploadResponse.headers.get('content-type');
      let document;
      if (contentType && contentType.includes('application/json')) {
        document = await uploadResponse.json();
      } else {
        const text = await uploadResponse.text();
        throw new Error(text || t.errorLoad);
      }

      setRegistrations(prev => prev.map(reg => {
        if (reg.id === registrationId) {
          return {
            ...reg,
            documents: [...(reg.documents || []), document],
          };
        }
        return reg;
      }));
    } catch (err) {
      setUploadError(err instanceof Error ? err.message : t.errorLoad);
      console.error(err);
    } finally {
      setIsUploading(false);
    }
  };

  const handleDeleteDocument = async (registrationId: string, documentId: string) => {
    if (!registrationId || !documentId) return;
    setIsDeleting(documentId);
    try {
      const response = await fetch(`/api/admin/registrations/${registrationId}/documents/${documentId}`, {
        method: 'DELETE',
      });
      if (!response.ok) {
        throw new Error(t.errorDelete);
      }
      setRegistrations(prev => prev.map(reg => {
        if (reg.id === registrationId) {
          return {
            ...reg,
            documents: reg.documents?.filter(doc => doc.id !== documentId) || [],
          };
        }
        return reg;
      }));
    } catch (error) {
      console.error('Error deleting document:', error);
      setError(t.errorDelete);
    } finally {
      setIsDeleting(null);
    }
  };

  const handleRestore = async () => {
    if (!restoreFile) return;

    setIsRestoring(true);
    setRestoreError(null);
    setRestoreSuccess(false);

    const formData = new FormData();
    formData.append('file', restoreFile);

    try {
      const response = await fetch('/api/admin/restore', {
        method: 'POST',
        body: formData,
      });

      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.message || 'Restore failed');
      }

      setRestoreSuccess(true);
      // Refresh the page after successful restore
      setTimeout(() => {
        window.location.reload();
      }, 2000);
    } catch (error: any) {
      setRestoreError(error?.message || 'An unexpected error occurred');
    } finally {
      setIsRestoring(false);
    }
  };

  const handleStatusUpdate = async (registrationId: string, newStatus: string) => {
    setIsUpdatingStatus(registrationId);
    try {
      const response = await fetch(`/api/admin/registrations/${registrationId}/status`, {
        method: 'PATCH',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          status: newStatus,
        }),
      });

      if (!response.ok) {
        throw new Error('Failed to update status');
      }

      // Update the registration in the list
      setRegistrations(prev => prev.map(reg =>
        reg.id === registrationId
          ? { ...reg, status: newStatus, updatedAt: new Date() }
          : reg
      ));

      // Update stats
      setStats(prev => ({
        total: prev.total,
        pending: registrations.filter(r => r.id !== registrationId && r.status === 'PENDING').length + (newStatus === 'PENDING' ? 1 : 0),
        approved: registrations.filter(r => r.id !== registrationId && r.status === 'APPROVED').length + (newStatus === 'APPROVED' ? 1 : 0),
        rejected: registrations.filter(r => r.id !== registrationId && r.status === 'REJECTED').length + (newStatus === 'REJECTED' ? 1 : 0),
      }));

    } catch (err) {
      console.error('Error updating status:', err);
      setError('Failed to update status');
    } finally {
      setIsUpdatingStatus(null);
    }
  };

  if (status === 'loading' || loading) {
    return (
      <LayoutWithSidebar>
        <div className={`flex justify-center items-center ${isMobile ? 'min-h-64' : 'min-h-96'}`}>
          <div className="text-center">
            <div className={`animate-spin rounded-full border-4 border-blue-500 border-t-transparent ${isMobile ? 'w-12 h-12' : 'w-16 h-16'} mx-auto mb-4`}></div>
            <p className={`text-gray-600 ${isMobile ? 'text-sm' : ''}`}>Loading admin panel...</p>
          </div>
        </div>
      </LayoutWithSidebar>
    );
  }

  if (!session || !canAccessAdmin(session)) {
    return null;
  }

  const adminLinks = [
    {
      title: 'Dashboard',
      description: 'View comprehensive admin dashboard with statistics and management tools',
      href: '/admin/dashboard',
      icon: '📊',
      color: 'from-blue-500 to-blue-600'
    },
    {
      title: 'Case Management',
      description: 'Create and manage legal cases, view applications, and assign lawyers',
      href: '/admin/case-management',
      icon: '⚖️',
      color: 'from-blue-600 to-purple-600'
    },
    {
      title: 'User Management',
      description: 'Manage user accounts, permissions, and access levels',
      href: '/admin/users',
      icon: '👥',
      color: 'from-green-500 to-green-600'
    },
    {
      title: 'Public Notifications',
      description: 'Manage banners, toasts, and engagement prompts for public visitors',
      href: '/admin/notifications',
      icon: '📢',
      color: 'from-red-500 to-red-600'
    },
    {
      title: 'Applications',
      description: 'Review and manage legal case applications from clients',
      href: '/admin/applications',
      icon: '📋',
      color: 'from-purple-500 to-purple-600'
    },
    {
      title: 'Registrations',
      description: 'View and manage user registrations across all cases',
      href: '/admin/registrations',
      icon: '📝',
      color: 'from-indigo-500 to-indigo-600'
    },
    {
      title: 'System Settings',
      description: 'Configure system settings and options',
      href: '/admin/options',
      icon: '⚙️',
      color: 'from-gray-500 to-gray-600'
    },
    {
      title: 'Admin Management',
      description: 'Grant or revoke admin privileges to users',
      href: '/admin/make-admin',
      icon: '👑',
      color: 'from-yellow-500 to-yellow-600'
    }
  ];

  return (
    <LayoutWithSidebar>
      <div className={`mx-auto ${isMobile ? 'px-2 py-4 max-w-full' : 'max-w-6xl px-4 py-8'}`}>
        {/* Header */}
        <div className={`text-center mb-8 bg-gradient-to-r from-blue-600 to-purple-600 text-white rounded-xl shadow-xl ${isMobile ? 'p-6' : 'p-8'}`}>
          <h1 className={`font-bold mb-2 ${isMobile ? 'text-2xl' : 'text-4xl'}`}>Admin Panel</h1>
          <p className={`${isMobile ? 'text-sm' : 'text-lg'}`}>
            Welcome back, {session.user.name}! Manage the multi-case legal platform from here.
          </p>
        </div>

        {/* Quick Stats */}
        <div className={`grid gap-4 mb-8 ${isMobile ? 'grid-cols-2' : 'grid-cols-2 md:grid-cols-4'}`}>
          <div className={`bg-white rounded-lg shadow-md border-l-4 border-blue-500 ${isMobile ? 'p-4' : 'p-6'}`}>
            <div className={`text-blue-600 mb-2 ${isMobile ? 'text-2xl' : 'text-3xl'}`}>👥</div>
            <div className={`font-bold text-gray-800 ${isMobile ? 'text-lg' : 'text-2xl'}`}>Users</div>
            <div className={`text-gray-600 ${isMobile ? 'text-xs' : 'text-sm'}`}>Total registered</div>
          </div>
          <div className={`bg-white rounded-lg shadow-md border-l-4 border-green-500 ${isMobile ? 'p-4' : 'p-6'}`}>
            <div className={`text-green-600 mb-2 ${isMobile ? 'text-2xl' : 'text-3xl'}`}>📋</div>
            <div className={`font-bold text-gray-800 ${isMobile ? 'text-lg' : 'text-2xl'}`}>Apps</div>
            <div className={`text-gray-600 ${isMobile ? 'text-xs' : 'text-sm'}`}>Applications</div>
          </div>
          <div className={`bg-white rounded-lg shadow-md border-l-4 border-purple-500 ${isMobile ? 'p-4' : 'p-6'}`}>
            <div className={`text-purple-600 mb-2 ${isMobile ? 'text-2xl' : 'text-3xl'}`}>📝</div>
            <div className={`font-bold text-gray-800 ${isMobile ? 'text-lg' : 'text-2xl'}`}>Regs</div>
            <div className={`text-gray-600 ${isMobile ? 'text-xs' : 'text-sm'}`}>Registrations</div>
          </div>
          <div className={`bg-white rounded-lg shadow-md border-l-4 border-yellow-500 ${isMobile ? 'p-4' : 'p-6'}`}>
            <div className={`text-yellow-600 mb-2 ${isMobile ? 'text-2xl' : 'text-3xl'}`}>👑</div>
            <div className={`font-bold text-gray-800 ${isMobile ? 'text-lg' : 'text-2xl'}`}>Admins</div>
            <div className={`text-gray-600 ${isMobile ? 'text-xs' : 'text-sm'}`}>Admin users</div>
          </div>
        </div>

        {/* Search Analytics Section */}
        <div className={`mb-8 bg-white rounded-xl shadow-xl border border-gray-200 ${isMobile ? 'p-6' : 'p-8'}`}>
          <h2 className={`font-bold text-gray-800 mb-4 ${isMobile ? 'text-xl' : 'text-2xl'}`}>Search Analytics</h2>
          {/* Filters */}
          <div className="mb-4 flex flex-wrap gap-4 items-center">
            <label className="text-sm font-medium text-gray-700">Date Range:
              <select
                className="ml-2 px-2 py-1 border rounded"
                value={analyticsDateRange}
                onChange={e => setAnalyticsDateRange(e.target.value)}
              >
                {DATE_RANGES.map(opt => (
                  <option key={opt.value} value={opt.value}>{opt.label}</option>
                ))}
              </select>
            </label>
            {analyticsDateRange === 'custom' && (
              <>
                <label className="text-sm font-medium text-gray-700">From:
                  <input
                    type="date"
                    className="ml-2 px-2 py-1 border rounded"
                    value={customStartDate}
                    onChange={e => setCustomStartDate(e.target.value)}
                    max={customEndDate || undefined}
                  />
                </label>
                <label className="text-sm font-medium text-gray-700">To:
                  <input
                    type="date"
                    className="ml-2 px-2 py-1 border rounded"
                    value={customEndDate}
                    onChange={e => setCustomEndDate(e.target.value)}
                    min={customStartDate || undefined}
                  />
                </label>
              </>
            )}
            <label className="text-sm font-medium text-gray-700">User Type:
              <select
                className="ml-2 px-2 py-1 border rounded"
                value={analyticsUserType}
                onChange={e => setAnalyticsUserType(e.target.value)}
              >
                {USER_TYPES.map(opt => (
                  <option key={opt.value} value={opt.value}>{opt.label}</option>
                ))}
              </select>
            </label>
            <label className="text-sm font-medium text-gray-700">Device:
              <select
                className="ml-2 px-2 py-1 border rounded"
                value={analyticsDeviceType}
                onChange={e => setAnalyticsDeviceType(e.target.value)}
              >
                {DEVICE_TYPES.map(opt => (
                  <option key={opt.value} value={opt.value}>{opt.label}</option>
                ))}
              </select>
            </label>
            <label className="text-sm font-medium text-gray-700">Search Type:
              <select
                className="ml-2 px-2 py-1 border rounded"
                value={analyticsSearchType}
                onChange={e => setAnalyticsSearchType(e.target.value)}
              >
                {SEARCH_TYPES.map(opt => (
                  <option key={opt.value} value={opt.value}>{opt.label}</option>
                ))}
              </select>
            </label>
            <label className="text-sm font-medium text-gray-700">Region:
              <select
                className="ml-2 px-2 py-1 border rounded"
                value={analyticsRegion}
                onChange={e => setAnalyticsRegion(e.target.value)}
              >
                {REGIONS.map(opt => (
                  <option key={opt.value} value={opt.value}>{opt.label}</option>
                ))}
              </select>
            </label>
            <label className="text-sm font-medium text-gray-700">Organization:
              <input
                type="text"
                className="ml-2 px-2 py-1 border rounded"
                placeholder="All organizations"
                value={analyticsOrganization === 'all' ? '' : analyticsOrganization}
                onChange={e => setAnalyticsOrganization(e.target.value || 'all')}
              />
            </label>
          </div>
          {/* Export Buttons */}
          <div className="mb-4 flex flex-wrap gap-2">
            <button
              className="bg-blue-600 text-white px-3 py-1 rounded hover:bg-blue-700 text-xs font-semibold"
              onClick={() => searchAnalytics && exportCSV(searchAnalytics.searchTrends, ['date', 'searches', 'unique_users'], 'search_trends.csv')}
            >
              Export Trends (CSV)
            </button>
            <button
              className="bg-green-600 text-white px-3 py-1 rounded hover:bg-green-700 text-xs font-semibold"
              onClick={() => searchAnalytics && exportExcel(searchAnalytics.popularQueries, ['query', 'count'], 'top_queries.csv')}
            >
              Export Top Queries (Excel)
            </button>
            <button
              className="bg-purple-600 text-white px-3 py-1 rounded hover:bg-purple-700 text-xs font-semibold"
              onClick={() => searchAnalytics && exportPDF('Search Trends', searchAnalytics.searchTrends, ['date', 'searches', 'unique_users'], 'search_trends.pdf')}
            >
              Export Trends (PDF)
            </button>
            <button
              className="bg-yellow-600 text-white px-3 py-1 rounded hover:bg-yellow-700 text-xs font-semibold"
              onClick={() => searchAnalytics && exportPDF('Top Queries', searchAnalytics.popularQueries, ['query', 'count'], 'top_queries.pdf')}
            >
              Export Top Queries (PDF)
            </button>
          </div>
          {searchAnalyticsLoading ? (
            <div className="text-gray-500">Loading search analytics...</div>
          ) : searchAnalyticsError ? (
            <div className="text-red-500">{searchAnalyticsError}</div>
          ) : searchAnalytics ? (
            <>
              <div className={`grid gap-4 mb-6 ${isMobile ? 'grid-cols-2' : 'grid-cols-4'}`}>
                <div className="bg-blue-50 rounded-lg p-4 text-center">
                  <div className="text-2xl font-bold text-blue-700">{searchAnalytics.totalSearches}</div>
                  <div className="text-xs text-gray-600 mt-1">Total Searches</div>
                </div>
                <div className="bg-green-50 rounded-lg p-4 text-center">
                  <div className="text-2xl font-bold text-green-700">{searchAnalytics.uniqueUsers}</div>
                  <div className="text-xs text-gray-600 mt-1">Unique Users</div>
                </div>
                <div className="bg-purple-50 rounded-lg p-4 text-center">
                  <div className="text-2xl font-bold text-purple-700">{searchAnalytics.averageSearchTime.toFixed(0)} ms</div>
                  <div className="text-xs text-gray-600 mt-1">Avg. Search Time</div>
                </div>
                <div className="bg-yellow-50 rounded-lg p-4 text-center">
                  <div className="text-2xl font-bold text-yellow-700">{searchAnalytics.clickThroughRate.toFixed(1)}%</div>
                  <div className="text-xs text-gray-600 mt-1">Click-Through Rate</div>
                </div>
              </div>
              {/* Charts Row */}
              <div className={`grid gap-8 mb-8 ${isMobile ? 'grid-cols-1' : 'grid-cols-2'}`}>
                {/* Line Chart: Trends */}
                <div className="bg-gray-50 rounded-lg p-4">
                  <h3 className="font-semibold text-gray-700 mb-2">Search Trends (Last 30 Days)</h3>
                  <ResponsiveContainer width="100%" height={260}>
                    <LineChart data={searchAnalytics.searchTrends} margin={{ top: 10, right: 20, left: 0, bottom: 0 }}>
                      <CartesianGrid strokeDasharray="3 3" />
                      <XAxis dataKey="date" tick={{ fontSize: 12 }} />
                      <YAxis tick={{ fontSize: 12 }} />
                      <Tooltip />
                      <Legend />
                      <Line type="monotone" dataKey="searches" stroke="#2563eb" name="Searches" strokeWidth={2} />
                      <Line type="monotone" dataKey="unique_users" stroke="#16a34a" name="Unique Users" strokeWidth={2} />
                    </LineChart>
                  </ResponsiveContainer>
                </div>
                {/* Bar Chart: Top Queries */}
                <div className="bg-gray-50 rounded-lg p-4">
                  <h3 className="font-semibold text-gray-700 mb-2">Top Queries</h3>
                  <ResponsiveContainer width="100%" height={260}>
                    <BarChart data={searchAnalytics.popularQueries} layout="vertical" margin={{ top: 10, right: 20, left: 0, bottom: 0 }}>
                      <CartesianGrid strokeDasharray="3 3" />
                      <XAxis type="number" tick={{ fontSize: 12 }} allowDecimals={false} />
                      <YAxis dataKey="query" type="category" tick={{ fontSize: 12 }} width={120} />
                      <Tooltip />
                      <Bar dataKey="count" fill="#6366f1" name="Count">
                        <LabelList dataKey="count" position="right" />
                      </Bar>
                    </BarChart>
                  </ResponsiveContainer>
                </div>
              </div>
              {/* Fallback Tables */}
              <div className="mb-6">
                <h3 className="font-semibold text-gray-700 mb-2">Top Queries (Table)</h3>
                <div className="overflow-x-auto">
                  <table className="min-w-full text-sm border">
                    <thead>
                      <tr className="bg-gray-100">
                        <th className="px-3 py-2 text-left">Query</th>
                        <th className="px-3 py-2 text-left">Count</th>
                      </tr>
                    </thead>
                    <tbody>
                      {searchAnalytics.popularQueries.map((q: any, i: number) => (
                        <tr key={q.query} className={i % 2 === 0 ? 'bg-white' : 'bg-gray-50'}>
                          <td className="px-3 py-2 font-mono">{q.query}</td>
                          <td className="px-3 py-2">{q.count}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              </div>
              <div>
                <h3 className="font-semibold text-gray-700 mb-2">Search Trends (Table)</h3>
                <div className="overflow-x-auto">
                  <table className="min-w-full text-xs border">
                    <thead>
                      <tr className="bg-gray-100">
                        <th className="px-2 py-1 text-left">Date</th>
                        <th className="px-2 py-1 text-left">Searches</th>
                        <th className="px-2 py-1 text-left">Unique Users</th>
                      </tr>
                    </thead>
                    <tbody>
                      {searchAnalytics.searchTrends.map((trend: any, i: number) => (
                        <tr key={trend.date} className={i % 2 === 0 ? 'bg-white' : 'bg-gray-50'}>
                          <td className="px-2 py-1 font-mono">{trend.date}</td>
                          <td className="px-2 py-1">{trend.searches}</td>
                          <td className="px-2 py-1">{trend.unique_users}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              </div>
            </>
          ) : null}
        </div>

        {/* Admin Links Grid */}
        <div className={`grid gap-6 ${isMobile ? 'grid-cols-1' : 'md:grid-cols-2 lg:grid-cols-3'}`}>
          {adminLinks.map((link, index) => (
            <div
              key={link.href}
              className={`bg-gradient-to-br ${link.color} text-white rounded-xl shadow-xl hover:shadow-2xl transform hover:scale-105 transition-all duration-200 cursor-pointer ${isMobile ? 'p-6' : 'p-8'}`}
              onClick={() => router.push(link.href)}
            >
              <div className={`text-center mb-4 ${isMobile ? 'text-4xl' : 'text-5xl'}`}>{link.icon}</div>
              <h2 className={`font-bold text-center mb-3 ${isMobile ? 'text-lg' : 'text-xl'}`}>{link.title}</h2>
              <p className={`text-center leading-relaxed opacity-90 ${isMobile ? 'text-sm' : ''}`}>{link.description}</p>
              <div className="text-center mt-4">
                <div className={`inline-block bg-white/20 rounded-lg font-semibold hover:bg-white/30 transition-all duration-200 ${isMobile ? 'px-4 py-2 text-sm' : 'px-6 py-3'}`}>
                  Access {link.title}
                </div>
              </div>
            </div>
          ))}
        </div>

        {/* Recent Activity */}
        <div className={`mt-8 bg-white rounded-xl shadow-xl border border-gray-200 ${isMobile ? 'p-6' : 'p-8'}`}>
          <h2 className={`font-bold text-gray-800 mb-4 ${isMobile ? 'text-xl' : 'text-2xl'}`}>Recent Activity</h2>
          <div className="space-y-4">
            <div className={`flex items-center space-x-4 border-l-4 border-indigo-500 ${isMobile ? 'pl-3 py-2' : 'pl-4 py-3'} bg-indigo-50 rounded-r-lg`}>
              <div className={`text-indigo-600 ${isMobile ? 'text-lg' : 'text-xl'}`}>⚖️</div>
              <div className="flex-1">
                <div className={`font-semibold text-gray-800 ${isMobile ? 'text-sm' : ''}`}>Bordeaux Class Action Case Active</div>
                <div className={`text-gray-600 ${isMobile ? 'text-xs' : 'text-sm'}`}>Case management system operational</div>
              </div>
            </div>
            <div className={`flex items-center space-x-4 border-l-4 border-blue-500 ${isMobile ? 'pl-3 py-2' : 'pl-4 py-3'} bg-blue-50 rounded-r-lg`}>
              <div className={`text-blue-600 ${isMobile ? 'text-lg' : 'text-xl'}`}>👥</div>
              <div className="flex-1">
                <div className={`font-semibold text-gray-800 ${isMobile ? 'text-sm' : ''}`}>ADW Law Firm Configured</div>
                <div className={`text-gray-600 ${isMobile ? 'text-xs' : 'text-sm'}`}>4 lawyers + Justin Wee (ADMIN) ready</div>
              </div>
            </div>
            <div className={`flex items-center space-x-4 border-l-4 border-purple-500 ${isMobile ? 'pl-3 py-2' : 'pl-4 py-3'} bg-purple-50 rounded-r-lg`}>
              <div className={`text-purple-600 ${isMobile ? 'text-lg' : 'text-xl'}`}>🤖</div>
              <div className="flex-1">
                <div className={`font-semibold text-gray-800 ${isMobile ? 'text-sm' : ''}`}>AI Assignment System Ready</div>
                <div className={`text-gray-600 ${isMobile ? 'text-xs' : 'text-sm'}`}>Smart case matching enabled</div>
              </div>
            </div>
          </div>
        </div>

        {/* Quick Actions */}
        <div className={`mt-8 text-center space-y-4 ${isMobile ? '' : 'space-y-0 space-x-4 flex flex-wrap justify-center'}`}>
          <button
            onClick={() => router.push('/admin/case-management')}
            className={`bg-indigo-600 text-white rounded-lg font-semibold shadow-lg hover:bg-indigo-700 hover:scale-105 transition-all duration-200 ${isMobile ? 'w-full px-6 py-3' : 'px-8 py-4'}`}
          >
            ⚖️ Manage Cases
          </button>
          <button
            onClick={() => router.push('/admin/applications')}
            className={`bg-blue-600 text-white rounded-lg font-semibold shadow-lg hover:bg-blue-700 hover:scale-105 transition-all duration-200 ${isMobile ? 'w-full px-6 py-3' : 'px-8 py-4'}`}
          >
            Review Applications
          </button>
          <button
            onClick={() => router.push('/admin/users')}
            className={`bg-green-600 text-white rounded-lg font-semibold shadow-lg hover:bg-green-700 hover:scale-105 transition-all duration-200 ${isMobile ? 'w-full px-6 py-3' : 'px-8 py-4'}`}
          >
            Manage Users
          </button>
          <button
            onClick={() => router.push('/admin/notifications')}
            className={`bg-red-600 text-white rounded-lg font-semibold shadow-lg hover:bg-red-700 hover:scale-105 transition-all duration-200 ${isMobile ? 'w-full px-6 py-3' : 'px-8 py-4'}`}
          >
            📢 Public Notifications
          </button>
          <button
            onClick={() => router.push('/admin/dashboard')}
            className={`bg-purple-600 text-white rounded-lg font-semibold shadow-lg hover:bg-purple-700 hover:scale-105 transition-all duration-200 ${isMobile ? 'w-full px-6 py-3' : 'px-8 py-4'}`}
          >
            View Dashboard
          </button>
        </div>
      </div>
    </LayoutWithSidebar>
  );
}

CasperSecurity Mini