import React, { useState, useCallback, useEffect } from 'react';
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
import { useParams, useNavigate } from 'react-router-dom';
import { toast } from 'react-toastify';
import {
  Download,
  RefreshCw,
  Settings,
  AlertCircle,
  Activity,
  TrendingUp,
  Clock,
  Users,
  Shield
} from 'lucide-react';

import { SearchFilters } from './SearchFilters';
import { VirtualizedLogTable } from './VirtualizedLogTable';
import { LogDetailModal } from './LogDetailModal';
import { ExportModal } from './ExportModal';
import { RealTimeIndicator } from './RealTimeIndicator';
import { useWebSocket } from '@/hooks/useWebSocket';
import auditApi from '@/services/api';
import {
  AuditLogEntry,
  AuditSearchFilters,
  SavedSearch,
  AuditDashboardStats,
  AuditExportRequest
} from '@/types/audit';

const WEBSOCKET_URL = process.env.NODE_ENV === 'production'
  ? `wss://${window.location.host}/ws/audit`
  : 'ws://localhost:8080/ws/audit';

export const AuditLogViewer: React.FC = () => {
  const { logId } = useParams<{ logId?: string }>();
  const navigate = useNavigate();

  // Component state
  const [filters, setFilters] = useState<AuditSearchFilters>({
    dateRange: {},
    users: [],
    actions: [],
    resources: [],
    severity: [],
    complianceFrameworks: [],
    tags: []
  });

  const [selectedLogIds, setSelectedLogIds] = useState<Set<string>>(new Set());
  const [selectedLog, setSelectedLog] = useState<AuditLogEntry | null>(null);
  const [isDetailModalOpen, setIsDetailModalOpen] = useState(false);
  const [isExportModalOpen, setIsExportModalOpen] = useState(false);
  const [realTimeEnabled, setRealTimeEnabled] = useState(true);
  const [newLogCount, setNewLogCount] = useState(0);
  const [realtimeQueue, setRealtimeQueue] = useState<AuditLogEntry[]>([]);

  // Fetch logs with infinite query for pagination
  const {
    data: logsData,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    isLoading: isLogsLoading,
    refetch: refetchLogs,
    error: logsError
  } = useInfiniteQuery({
    queryKey: ['auditLogs', filters],
    queryFn: ({ pageParam = 0 }) =>
      auditApi.getLogs(filters, pageParam, 50),
    getNextPageParam: (lastPage) =>
      lastPage.hasMore ? lastPage.page + 1 : undefined,
    staleTime: 30 * 1000, // 30 seconds
    enabled: true,
    refetchOnWindowFocus: false
  });

  // Fetch saved searches
  const { data: savedSearches = [] } = useQuery({
    queryKey: ['savedSearches'],
    queryFn: () => auditApi.getSavedSearches(),
    staleTime: 5 * 60 * 1000
  });

  // Fetch dashboard stats
  const { data: dashboardStats } = useQuery({
    queryKey: ['dashboardStats'],
    queryFn: () => auditApi.getDashboardStats(),
    refetchInterval: 30 * 1000 // Refresh every 30 seconds
  });

  // Flatten logs from all pages
  const allLogs = React.useMemo(() => {
    if (!logsData) return [];
    return [
      ...realtimeQueue, // New logs from WebSocket at the top
      ...logsData.pages.flatMap(page => page.logs)
    ];
  }, [logsData, realtimeQueue]);

  const totalCount = logsData?.pages[0]?.total || 0;

  // WebSocket for real-time updates
  const { isConnected, lastMessage, reconnect, readyState, reconnectAttempts } = useWebSocket({
    url: WEBSOCKET_URL,
    shouldReconnect: realTimeEnabled,
    onNewAuditLog: (log: AuditLogEntry) => {
      if (realTimeEnabled) {
        setRealtimeQueue(prev => [log, ...prev.slice(0, 49)]); // Keep last 50 realtime logs
        setNewLogCount(prev => prev + 1);

        // Show toast for critical severity logs
        if (log.severity === 'critical') {
          toast.error(`Critical audit event: ${log.action.description}`, {
            position: 'top-right',
            autoClose: 10000
          });
        }
      }
    },
    onComplianceAlert: (alert: any) => {
      toast.warning(`Compliance alert: ${alert.message}`, {
        position: 'top-right',
        autoClose: 8000
      });
    },
    onError: (error) => {
      console.error('WebSocket error:', error);
      toast.error('Real-time connection error');
    }
  });

  // Load specific log from URL parameter
  useEffect(() => {
    if (logId) {
      auditApi.getLog(logId)
        .then(log => {
          setSelectedLog(log);
          setIsDetailModalOpen(true);
        })
        .catch(error => {
          toast.error(`Failed to load log: ${error.message}`);
          navigate('/audit');
        });
    }
  }, [logId, navigate]);

  // Reset new log count when real-time is disabled or filters change
  useEffect(() => {
    setNewLogCount(0);
    setRealtimeQueue([]);
  }, [realTimeEnabled, filters]);

  // Handle filter changes
  const handleFiltersChange = useCallback((newFilters: AuditSearchFilters) => {
    setFilters(newFilters);
    setNewLogCount(0);
    setRealtimeQueue([]);
  }, []);

  // Handle save search
  const handleSaveSearch = useCallback(async (name: string, description?: string) => {
    try {
      await auditApi.createSavedSearch({
        name,
        description,
        filters,
        isPublic: false,
        createdBy: 'current-user' // This would come from auth context
      });
      toast.success('Search saved successfully');
    } catch (error) {
      toast.error('Failed to save search');
    }
  }, [filters]);

  // Handle load saved search
  const handleLoadSavedSearch = useCallback((search: SavedSearch) => {
    setFilters(search.filters);
    toast.success(`Loaded search: ${search.name}`);
  }, []);

  // Handle row click
  const handleRowClick = useCallback((log: AuditLogEntry) => {
    setSelectedLog(log);
    setIsDetailModalOpen(true);
    navigate(`/audit/${log.id}`, { replace: true });
  }, [navigate]);

  // Handle modal close
  const handleCloseDetailModal = useCallback(() => {
    setIsDetailModalOpen(false);
    setSelectedLog(null);
    navigate('/audit', { replace: true });
  }, [navigate]);

  // Handle view correlated logs
  const handleViewCorrelated = useCallback(async (requestId: string) => {
    try {
      const correlatedLogs = await auditApi.getCorrelatedLogs(requestId);
      // Set filters to show only correlated logs
      setFilters({
        ...filters,
        requestId
      });
      handleCloseDetailModal();
      toast.success(`Found ${correlatedLogs.length} correlated logs`);
    } catch (error) {
      toast.error('Failed to load correlated logs');
    }
  }, [filters, handleCloseDetailModal]);

  // Handle view session logs
  const handleViewSession = useCallback(async (sessionId: string) => {
    try {
      const sessionLogs = await auditApi.getLogsBySession(sessionId);
      setFilters({
        ...filters,
        sessionId
      });
      handleCloseDetailModal();
      toast.success(`Found ${sessionLogs.length} session logs`);
    } catch (error) {
      toast.error('Failed to load session logs');
    }
  }, [filters, handleCloseDetailModal]);

  // Handle export
  const handleExport = useCallback(async (request: AuditExportRequest) => {
    try {
      const blob = await auditApi.exportLogs({
        ...request,
        filters
      });
      return blob;
    } catch (error) {
      toast.error('Export failed');
      throw error;
    }
  }, [filters]);

  // Handle real-time toggle
  const handleToggleRealTime = useCallback(() => {
    setRealTimeEnabled(prev => !prev);
    if (!realTimeEnabled) {
      setNewLogCount(0);
    }
  }, [realTimeEnabled]);

  // Handle refresh
  const handleRefresh = useCallback(() => {
    refetchLogs();
    setNewLogCount(0);
    setRealtimeQueue([]);
  }, [refetchLogs]);

  if (logsError) {
    return (
      <div className="flex flex-col items-center justify-center h-64">
        <AlertCircle className="h-12 w-12 text-error mb-4" />
        <h3 className="text-lg font-semibold mb-2">Error Loading Logs</h3>
        <p className="text-base-content/60 mb-4 text-center max-w-md">
          {logsError.message || 'An unexpected error occurred while loading audit logs.'}
        </p>
        <button onClick={handleRefresh} className="btn btn-primary">
          <RefreshCw className="h-4 w-4 mr-2" />
          Retry
        </button>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      {/* Dashboard Stats */}
      {dashboardStats && (
        <div className="grid grid-cols-4 gap-4">
          <div className="metric-card">
            <div className="flex items-center justify-between">
              <div>
                <p className="text-sm text-base-content/60">Total Events</p>
                <p className="text-2xl font-bold">{dashboardStats.totalEvents.toLocaleString()}</p>
              </div>
              <Activity className="h-8 w-8 text-primary" />
            </div>
          </div>
          <div className="metric-card">
            <div className="flex items-center justify-between">
              <div>
                <p className="text-sm text-base-content/60">Success Rate</p>
                <p className="text-2xl font-bold">{(dashboardStats.successRate * 100).toFixed(1)}%</p>
              </div>
              <TrendingUp className="h-8 w-8 text-success" />
            </div>
          </div>
          <div className="metric-card">
            <div className="flex items-center justify-between">
              <div>
                <p className="text-sm text-base-content/60">Critical Events</p>
                <p className="text-2xl font-bold">{dashboardStats.criticalEvents}</p>
              </div>
              <AlertCircle className="h-8 w-8 text-error" />
            </div>
          </div>
          <div className="metric-card">
            <div className="flex items-center justify-between">
              <div>
                <p className="text-sm text-base-content/60">Compliance Score</p>
                <p className="text-2xl font-bold">{dashboardStats.complianceScore}%</p>
              </div>
              <Shield className="h-8 w-8 text-primary" />
            </div>
          </div>
        </div>
      )}

      {/* Controls Bar */}
      <div className="flex items-center justify-between">
        <div className="flex items-center space-x-4">
          <RealTimeIndicator
            readyState={readyState}
            lastMessageTime={lastMessage?.timestamp}
            newLogCount={newLogCount}
            onToggleRealTime={handleToggleRealTime}
            onReconnect={reconnect}
            isEnabled={realTimeEnabled}
            reconnectAttempts={reconnectAttempts}
          />
        </div>

        <div className="flex items-center space-x-2">
          <button
            onClick={handleRefresh}
            className="btn btn-ghost btn-sm"
            disabled={isLogsLoading}
          >
            <RefreshCw className={`h-4 w-4 ${isLogsLoading ? 'animate-spin' : ''}`} />
            Refresh
          </button>

          <button
            onClick={() => setIsExportModalOpen(true)}
            className="btn btn-outline btn-sm"
            disabled={allLogs.length === 0}
          >
            <Download className="h-4 w-4 mr-1" />
            Export
          </button>

          {selectedLogIds.size > 0 && (
            <div className="flex items-center space-x-2">
              <span className="text-sm text-base-content/60">
                {selectedLogIds.size} selected
              </span>
              <button
                onClick={() => setSelectedLogIds(new Set())}
                className="btn btn-ghost btn-sm"
              >
                Clear
              </button>
            </div>
          )}
        </div>
      </div>

      {/* Search Filters */}
      <SearchFilters
        onFiltersChange={handleFiltersChange}
        onSaveSearch={handleSaveSearch}
        savedSearches={savedSearches}
        onLoadSavedSearch={handleLoadSavedSearch}
        isLoading={isLogsLoading}
      />

      {/* Results Info */}
      {!isLogsLoading && (
        <div className="flex items-center justify-between text-sm text-base-content/60">
          <div className="flex items-center space-x-4">
            <span>
              Showing {allLogs.length.toLocaleString()} of {totalCount.toLocaleString()} logs
            </span>
            {newLogCount > 0 && (
              <span className="text-primary">
                ({newLogCount} new in real-time)
              </span>
            )}
          </div>
          {isConnected && (
            <div className="flex items-center space-x-1 text-success">
              <div className="w-2 h-2 bg-success rounded-full animate-pulse"></div>
              <span>Live</span>
            </div>
          )}
        </div>
      )}

      {/* Log Table */}
      <VirtualizedLogTable
        logs={allLogs}
        isLoading={isLogsLoading || isFetchingNextPage}
        hasNextPage={hasNextPage || false}
        fetchNextPage={fetchNextPage}
        onRowClick={handleRowClick}
        onViewCorrelated={handleViewCorrelated}
        onViewSession={handleViewSession}
        selectedLogIds={selectedLogIds}
        onSelectionChange={setSelectedLogIds}
      />

      {/* Log Detail Modal */}
      <LogDetailModal
        log={selectedLog}
        isOpen={isDetailModalOpen}
        onClose={handleCloseDetailModal}
        onViewCorrelated={handleViewCorrelated}
        onViewSession={handleViewSession}
      />

      {/* Export Modal */}
      <ExportModal
        isOpen={isExportModalOpen}
        onClose={() => setIsExportModalOpen(false)}
        logs={allLogs}
        filters={filters}
        totalCount={totalCount}
        onExport={handleExport}
      />
    </div>
  );
};

export default AuditLogViewer;
