import { useState, useEffect, useRef } from 'react';
import { useAuthStore } from '../../store/authStore';
import { API_BASE_URL } from '../../services/api';

interface RequestMetrics {
  request_id: string;
  path: string;
  method: string;
  elapsed_time_ms: number;
  cpu: {
    user_time_ms: number;
    system_time_ms: number;
    total_time_ms: number;
    system_percent: number;
  };
  memory: {
    delta_bytes: number;
    delta_mb: number;
    final_rss_mb: number;
    system_used_percent: number;
  };
  io: {
    read_bytes: number;
    read_mb: number;
    write_bytes: number;
    write_mb: number;
  };
  timestamp: number;
}

interface ResourceDebugOverlayProps {
  enabled: boolean;
}

export default function ResourceDebugOverlay({ enabled }: ResourceDebugOverlayProps) {
  const { user } = useAuthStore();
  const [metrics, setMetrics] = useState<RequestMetrics[]>([]);
  const [isVisible, setIsVisible] = useState(false);
  const [pageLoadStart, setPageLoadStart] = useState<number | null>(null);
  const requestIdRef = useRef<string | null>(null);
  const metricsRef = useRef<RequestMetrics[]>([]);
  const originalFetchRef = useRef<typeof fetch | null>(null);
  const nativeFetchRef = useRef<typeof fetch | null>(null); // Store native fetch separately

  // Check if user is admin/developer
  const isAdminOrDeveloper = user?.role === 'admin' || user?.role === 'developer';

  // Track page load start and intercept fetch requests
  useEffect(() => {
    if (!enabled || !isAdminOrDeveloper) {
      // Restore native fetch if disabled
      if (nativeFetchRef.current) {
        window.fetch = nativeFetchRef.current;
        nativeFetchRef.current = null;
        originalFetchRef.current = null;
      }
      return;
    }
    
    setPageLoadStart(performance.now());
    
    // Store native fetch and create bound version
    if (!nativeFetchRef.current) {
      nativeFetchRef.current = window.fetch; // Store actual native fetch
      originalFetchRef.current = window.fetch.bind(window); // Create bound version for calling
    }
    
    // Intercept fetch requests to track API calls
    window.fetch = async function(...args) {
      const startTime = performance.now();
      const [url, options = {}] = args;
      
      // Don't intercept our own metrics fetch calls to avoid infinite loops
      const urlString = typeof url === 'string' ? url : url.toString();
      if (urlString.includes('/request-metrics/')) {
        // Use native fetch directly for metrics calls
        return nativeFetchRef.current!.apply(window, args as [RequestInfo | URL, RequestInit?]);
      }
      
      // Add debug header to enable tracking
      const headers = new Headers(options.headers || {});
      headers.set('X-Debug-Resource-Tracking', 'true');
      
      // Use bound fetch to preserve context
      const response = await originalFetchRef.current!(url, {
        ...options,
        headers,
      });
      
      const endTime = performance.now();
      
      // Get request ID from response header
      const requestId = response.headers.get('X-Resource-Tracking-ID');
      if (requestId) {
        requestIdRef.current = requestId;
        // Fetch metrics after a delay to ensure backend has stored them
        // Use a slightly longer delay to avoid race conditions
        setTimeout(() => fetchRequestMetrics(requestId), 300);
      }
      
      return response;
    };
    
    return () => {
      // Restore native fetch on cleanup
      if (nativeFetchRef.current) {
        window.fetch = nativeFetchRef.current;
        nativeFetchRef.current = null;
        originalFetchRef.current = null;
      }
    };
  }, [enabled, isAdminOrDeveloper]);

  // Fetch metrics for a request - use fetchAPI to get proper authentication handling
  const fetchRequestMetrics = async (requestId: string, retryCount = 0) => {
    try {
      // Use fetchAPI which handles token refresh and authentication properly
      // But we need to use native fetch to avoid interception loop
      const nativeFetch = nativeFetchRef.current || window.fetch;
      const { token } = useAuthStore.getState();
      
      const headers: HeadersInit = {
        'Content-Type': 'application/json',
      };
      
      // Add JWT token if available
      if (token) {
        headers['Authorization'] = `Bearer ${token}`;
      }
      
      // Silently handle 404s and other errors - metrics might not exist for all requests
      try {
        const response = await nativeFetch.call(window, `${API_BASE_URL}/v1/system/request-metrics/${requestId}/`, {
          method: 'GET',
          headers,
          credentials: 'include', // Include session cookies for authentication
        });
        
        if (response.ok) {
          const data = await response.json();
          // Only log in debug mode to reduce console noise
          if (import.meta.env.DEV) {
            console.debug('Fetched metrics for request:', requestId, data);
          }
          metricsRef.current = [...metricsRef.current, data];
          setMetrics([...metricsRef.current]);
        } else if (response.status === 401) {
          // Token might be expired - try to refresh and retry once
          try {
            await useAuthStore.getState().refreshToken();
            const newToken = useAuthStore.getState().token;
            if (newToken) {
              const retryHeaders: HeadersInit = {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${newToken}`,
              };
              const retryResponse = await nativeFetch.call(window, `${API_BASE_URL}/v1/system/request-metrics/${requestId}/`, {
                method: 'GET',
                headers: retryHeaders,
                credentials: 'include',
              });
              if (retryResponse.ok) {
                const data = await retryResponse.json();
                metricsRef.current = [...metricsRef.current, data];
                setMetrics([...metricsRef.current]);
                return;
              }
            }
          } catch (refreshError) {
            // Refresh failed - silently ignore
          }
          // Silently ignore 401 errors - user might not be authenticated
        } else if (response.status === 404) {
          // Metrics not found - silently ignore (metrics might not exist for all requests)
          return;
        } else {
          // Other errors - silently ignore
          return;
        }
      } catch (error) {
        // Silently ignore all fetch errors (network errors, etc.)
        // Metrics are optional and not critical for functionality
        return;
      }
    } catch (error) {
      // Silently ignore all errors
      return;
    }
  };

  // Calculate page load time
  const pageLoadTime = pageLoadStart ? performance.now() - pageLoadStart : null;

  // Calculate totals
  const totals = metrics.reduce((acc, m) => ({
    elapsed_time_ms: acc.elapsed_time_ms + m.elapsed_time_ms,
    cpu_total_ms: acc.cpu_total_ms + m.cpu.total_time_ms,
    memory_delta_mb: acc.memory_delta_mb + m.memory.delta_mb,
    io_read_mb: acc.io_read_mb + m.io.read_mb,
    io_write_mb: acc.io_write_mb + m.io.write_mb,
  }), {
    elapsed_time_ms: 0,
    cpu_total_ms: 0,
    memory_delta_mb: 0,
    io_read_mb: 0,
    io_write_mb: 0,
  });

  // Find the slowest request
  const slowestRequest = metrics.length > 0 
    ? metrics.reduce((prev, current) => 
        (current.elapsed_time_ms > prev.elapsed_time_ms) ? current : prev
      )
    : null;

  // Find the request with highest CPU usage
  const highestCpuRequest = metrics.length > 0
    ? metrics.reduce((prev, current) =>
        (current.cpu.total_time_ms > prev.cpu.total_time_ms) ? current : prev
      )
    : null;

  // Find the request with highest memory usage
  const highestMemoryRequest = metrics.length > 0
    ? metrics.reduce((prev, current) =>
        (current.memory.delta_mb > prev.memory.delta_mb) ? current : prev
      )
    : null;

  if (!enabled || !isAdminOrDeveloper) return null;

  return (
    <>
      {/* Toggle Button - Fixed position */}
      <button
        onClick={() => setIsVisible(!isVisible)}
        className="fixed bottom-4 right-4 z-[99999] bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-lg shadow-lg text-sm font-medium flex items-center gap-2"
        title="Toggle Resource Debug Overlay"
      >
        <span>🔍</span>
        <span>Debug ({metrics.length})</span>
      </button>

      {/* Overlay */}
      {isVisible && (
        <div className="fixed bottom-20 right-4 z-[99998] bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-lg shadow-2xl w-[500px] max-h-[85vh] overflow-auto">
          <div className="sticky top-0 bg-gray-100 dark:bg-gray-800 px-4 py-3 border-b border-gray-300 dark:border-gray-700 flex justify-between items-center">
            <h3 className="font-semibold text-gray-900 dark:text-white">Resource Debug</h3>
            <button
              onClick={() => setIsVisible(false)}
              className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
            >
              ✕
            </button>
          </div>
          
          <div className="p-4 space-y-4">
            {/* Page Load Summary */}
            {pageLoadTime && (
              <div className="bg-blue-50 dark:bg-blue-900/20 p-3 rounded border border-blue-200 dark:border-blue-800">
                <h4 className="font-semibold text-blue-900 dark:text-blue-200 mb-2">Page Load Time</h4>
                <div className="text-sm text-blue-800 dark:text-blue-300">
                  {pageLoadTime.toFixed(2)} ms
                </div>
              </div>
            )}

            {/* Performance Summary - Highlight Culprits */}
            {metrics.length > 0 && (
              <div className="bg-yellow-50 dark:bg-yellow-900/20 p-3 rounded border border-yellow-200 dark:border-yellow-800">
                <h4 className="font-semibold text-yellow-900 dark:text-yellow-200 mb-2">⚠️ Performance Culprits</h4>
                <div className="text-xs space-y-2 text-yellow-800 dark:text-yellow-300">
                  {slowestRequest && (
                    <div>
                      <span className="font-semibold">Slowest Request:</span> {slowestRequest.method} {slowestRequest.path}
                      <br />
                      <span className="ml-4">Time: {slowestRequest.elapsed_time_ms.toFixed(2)} ms</span>
                    </div>
                  )}
                  {highestCpuRequest && highestCpuRequest.cpu.total_time_ms > 100 && (
                    <div>
                      <span className="font-semibold">Highest CPU:</span> {highestCpuRequest.method} {highestCpuRequest.path}
                      <br />
                      <span className="ml-4">CPU: {highestCpuRequest.cpu.total_time_ms.toFixed(2)} ms (System: {highestCpuRequest.cpu.system_percent.toFixed(1)}%)</span>
                    </div>
                  )}
                  {highestMemoryRequest && highestMemoryRequest.memory.delta_mb > 1 && (
                    <div>
                      <span className="font-semibold">Highest Memory:</span> {highestMemoryRequest.method} {highestMemoryRequest.path}
                      <br />
                      <span className="ml-4">Memory: {highestMemoryRequest.memory.delta_mb > 0 ? '+' : ''}{highestMemoryRequest.memory.delta_mb.toFixed(2)} MB</span>
                    </div>
                  )}
                </div>
              </div>
            )}

            {/* Totals */}
            {metrics.length > 0 && (
              <div className="bg-gray-50 dark:bg-gray-800 p-3 rounded border border-gray-200 dark:border-gray-700">
                <h4 className="font-semibold text-gray-900 dark:text-white mb-2">Request Totals</h4>
                <div className="text-xs space-y-1 text-gray-700 dark:text-gray-300">
                  <div>Total Requests: {metrics.length}</div>
                  <div>Total Time: {totals.elapsed_time_ms.toFixed(2)} ms</div>
                  <div>Total CPU Time: {totals.cpu_total_ms.toFixed(2)} ms</div>
                  <div>Total Memory Delta: {totals.memory_delta_mb > 0 ? '+' : ''}{totals.memory_delta_mb.toFixed(2)} MB</div>
                  <div>Total I/O Read: {totals.io_read_mb.toFixed(2)} MB</div>
                  <div>Total I/O Write: {totals.io_write_mb.toFixed(2)} MB</div>
                </div>
              </div>
            )}

            {/* Individual Requests - Detailed View */}
            <div className="space-y-2">
              <h4 className="font-semibold text-gray-900 dark:text-white">All Requests (Detailed)</h4>
              {metrics.length === 0 ? (
                <div className="text-sm text-gray-500 dark:text-gray-400">
                  No requests tracked yet. Navigate to trigger API calls.
                  <br />
                  <span className="text-xs">Make sure debug toggle is enabled in header.</span>
                </div>
              ) : (
                metrics.map((m, idx) => {
                  const isSlow = m.elapsed_time_ms > 1000;
                  const isHighCpu = m.cpu.total_time_ms > 100;
                  const isHighMemory = m.memory.delta_mb > 1;
                  
                  return (
                    <div 
                      key={idx} 
                      className={`p-3 rounded border text-xs ${
                        isSlow || isHighCpu || isHighMemory
                          ? 'bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800'
                          : 'bg-gray-50 dark:bg-gray-800 border-gray-200 dark:border-gray-700'
                      }`}
                    >
                      <div className="font-semibold text-gray-900 dark:text-white mb-2 flex items-center gap-2">
                        <span>{m.method}</span>
                        <span className="text-gray-600 dark:text-gray-400 truncate">{m.path}</span>
                        {(isSlow || isHighCpu || isHighMemory) && (
                          <span className="text-red-600 dark:text-red-400 text-xs">⚠️</span>
                        )}
                      </div>
                      <div className="space-y-1 text-gray-700 dark:text-gray-300">
                        <div className={isSlow ? 'font-semibold text-red-700 dark:text-red-300' : ''}>
                          ⏱️ Time: {m.elapsed_time_ms.toFixed(2)} ms
                        </div>
                        <div className={isHighCpu ? 'font-semibold text-red-700 dark:text-red-300' : ''}>
                          🔥 CPU: {m.cpu.total_time_ms.toFixed(2)} ms 
                          <span className="text-gray-500"> (User: {m.cpu.user_time_ms.toFixed(2)}ms, System: {m.cpu.system_time_ms.toFixed(2)}ms)</span>
                          <br />
                          <span className="ml-4 text-gray-500">System CPU: {m.cpu.system_percent.toFixed(1)}%</span>
                        </div>
                        <div className={isHighMemory ? 'font-semibold text-red-700 dark:text-red-300' : ''}>
                          💾 Memory: {m.memory.delta_mb > 0 ? '+' : ''}{m.memory.delta_mb.toFixed(2)} MB
                          <span className="text-gray-500"> (Final RSS: {m.memory.final_rss_mb.toFixed(2)} MB)</span>
                          <br />
                          <span className="ml-4 text-gray-500">System Memory: {m.memory.system_used_percent.toFixed(1)}%</span>
                        </div>
                        {m.io.read_mb > 0 && (
                          <div>
                            📖 I/O Read: {m.io.read_mb.toFixed(2)} MB ({m.io.read_bytes.toLocaleString()} bytes)
                          </div>
                        )}
                        {m.io.write_mb > 0 && (
                          <div>
                            📝 I/O Write: {m.io.write_mb.toFixed(2)} MB ({m.io.write_bytes.toLocaleString()} bytes)
                          </div>
                        )}
                      </div>
                    </div>
                  );
                })
              )}
            </div>

            {/* Clear Button */}
            {metrics.length > 0 && (
              <button
                onClick={() => {
                  setMetrics([]);
                  metricsRef.current = [];
                  setPageLoadStart(performance.now());
                }}
                className="w-full bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-900 dark:text-white px-3 py-2 rounded text-sm"
              >
                Clear Metrics
              </button>
            )}
          </div>
        </div>
      )}
    </>
  );
}

