import { useState, useMemo, useEffect, lazy, Suspense } from 'react'
import { useDatabaseTraceData } from '../../hooks/useDatabaseTraceData'
import { getUrlParams, updateUrlWithTraceId } from '../../App'
import RequestFilters from './RequestFilters'
import RequestsTable from './RequestsTable'
import ColumnSettings from './ColumnSettings'
import styles from './HTTPRequestViewer.module.css'

// Lazy load 3D viewers to reduce main bundle size
const BabylonViewer = lazy(() => import('../../BabylonViewer'))
const BabylonTimelineViewer = lazy(() => import('../../BabylonTimelineViewer'))

// Loading component for 3D viewers
const ThreeDViewerLoading = () => (
  <div style={{
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    height: '500px',
    background: '#f8f9fa',
    borderRadius: '8px'
  }}>
    <div style={{
      width: '50px',
      height: '50px',
      border: '4px solid #e3f2fd',
      borderTop: '4px solid #2196f3',
      borderRadius: '50%',
      animation: 'spin 1s linear infinite',
      marginBottom: '20px'
    }} />
    <div style={{ color: '#6c757d', fontSize: '16px' }}>
      Loading 3D Viewer...
    </div>
    <div style={{ color: '#9e9e9e', fontSize: '14px', marginTop: '8px' }}>
      Initializing Babylon.js
    </div>
    <style>{`
      @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
      }
    `}</style>
  </div>
)

// Imported utilities
import { ITEMS_PER_PAGE, SSIM_SIMILARITY_THRESHOLD } from './lib/httpRequestConstants'
import { extractScreenshots, findUniqueScreenshots } from './lib/screenshotUtils'
import { processHTTPRequests } from './lib/httpRequestProcessor'
import { analyzeCDN, analyzeQueueReason } from './lib/analysisUtils'
import { addRequestPostProcessing } from './lib/requestPostProcessor'
import { assignConnectionNumbers } from './lib/connectionUtils'

// Import types
import type { HTTPRequest, ScreenshotEvent } from './types/httpRequest'
import HTTPRequestLoading from "./HTTPRequestLoading.tsx";
import sortRequests from "./lib/sortRequests.ts";
import PaginationControls from "./PaginationControls.tsx";
import { exportRequestsToCSV, downloadCSV } from './lib/csvExport';


interface HTTPRequestViewerProps {
  traceId: string | null
}

export default function HTTPRequestViewer({ traceId }: HTTPRequestViewerProps) {
  const { traceData, loading, error } = useDatabaseTraceData(traceId)
  const [currentPage, setCurrentPage] = useState(1)
  const [searchTerm, setSearchTerm] = useState('')
  const [resourceTypeFilter, setResourceTypeFilter] = useState<string>('all')
  const [protocolFilter, setProtocolFilter] = useState<string>('all')
  const [hostnameFilter, setHostnameFilter] = useState<string>('all')
  const [priorityFilter, setPriorityFilter] = useState<string>('all')
  const [showQueueAnalysis, setShowQueueAnalysis] = useState(false)
  const [showScreenshots, setShowScreenshots] = useState(false)
  // 3D viewer state - initialized from URL
  const [show3DViewer, setShow3DViewer] = useState(false)
  const [showTimelineViewer, setShowTimelineViewer] = useState(false)
  
  // Column visibility state - default visible columns as requested
  const [visibleColumns, setVisibleColumns] = useState(() => {
    const saved = localStorage.getItem('httpRequestTableColumns')
    if (saved) {
      try {
        return JSON.parse(saved)
      } catch (e) {
        console.warn('Failed to parse saved column settings, using defaults')
      }
    }
    // Default visible columns
    return {
      expand: true,
      method: false,
      status: false,
      type: false,
      priority: false,
      url: true,
      connectionNumber: false,
      requestNumber: false,
      startTime: true,
      queueTime: false,
      dns: false,
      connection: false,
      serverLatency: false,
      duration: false,
      totalResponseTime: true,
      dataRate: true,
      size: false,
      contentLength: true,
      protocol: false,
      cdn: false,
      cache: false
    }
  })
  const [columnSettingsOpen, setColumnSettingsOpen] = useState(false)

  // Initialize 3D view state from URL on component mount and handle URL changes
  useEffect(() => {
    const updateFrom3DUrl = () => {
      const { threeDView } = getUrlParams()
      setShow3DViewer(threeDView === 'network')
      setShowTimelineViewer(threeDView === 'timeline')
    }

    // Set initial state
    updateFrom3DUrl()
    
    // Listen for URL changes (back/forward navigation)
    const handlePopState = () => updateFrom3DUrl()
    window.addEventListener('popstate', handlePopState)
    
    return () => window.removeEventListener('popstate', handlePopState)
  }, [])

  // Handle 3D view changes and update URL
  const handle3DViewerToggle = (enabled: boolean) => {
    const { traceId, view } = getUrlParams()
    setShow3DViewer(enabled)
    setShowTimelineViewer(false) // Ensure only one 3D view is active
    updateUrlWithTraceId(traceId, view, enabled ? 'network' : null)
  }

  const handleTimelineViewerToggle = (enabled: boolean) => {
    const { traceId, view } = getUrlParams()
    setShowTimelineViewer(enabled)
    setShow3DViewer(false) // Ensure only one 3D view is active
    updateUrlWithTraceId(traceId, view, enabled ? 'timeline' : null)
  }
  const [ssimThreshold, setSsimThreshold] = useState(SSIM_SIMILARITY_THRESHOLD)
  const [pendingSSIMThreshold, setPendingSSIMThreshold] = useState(SSIM_SIMILARITY_THRESHOLD)
  const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set())

  const handleSSIMRecalculate = () => {
    setSsimThreshold(pendingSSIMThreshold)
  }

  // Column visibility handlers
  const handleColumnToggle = (column: string) => {
    const newVisibleColumns = {
      ...visibleColumns,
      [column]: !visibleColumns[column]
    }
    setVisibleColumns(newVisibleColumns)
    localStorage.setItem('httpRequestTableColumns', JSON.stringify(newVisibleColumns))
  }

  const handleShowAllColumns = () => {
    const allVisible = Object.keys(visibleColumns).reduce((acc, key) => {
      acc[key] = true
      return acc
    }, {} as Record<string, boolean>)
    setVisibleColumns(allVisible)
    localStorage.setItem('httpRequestTableColumns', JSON.stringify(allVisible))
  }

  const handleHideAllColumns = () => {
    const allHidden = Object.keys(visibleColumns).reduce((acc, key) => {
      acc[key] = key === 'expand' // Always keep expand column visible
      return acc
    }, {} as Record<string, boolean>)
    setVisibleColumns(allHidden)
    localStorage.setItem('httpRequestTableColumns', JSON.stringify(allHidden))
  }

  const handleResetDefaults = () => {
    const defaultColumns = {
      expand: true,
      method: false,
      status: false,
      type: false,
      priority: false,
      url: true,
      connectionNumber: false,
      requestNumber: false,
      startTime: true,
      queueTime: false,
      dns: false,
      connection: false,
      serverLatency: false,
      duration: false,
      totalResponseTime: true,
      dataRate: true,
      size: false,
      contentLength: true,
      protocol: false,
      cdn: false,
      cache: false
    }
    setVisibleColumns(defaultColumns)
    localStorage.setItem('httpRequestTableColumns', JSON.stringify(defaultColumns))
  }

  const httpRequests = useMemo(() => {
    if (!traceData) return []
    const httpRequests = processHTTPRequests(traceData.traceEvents)
    const sortedRequests = sortRequests(httpRequests)
    const processedRequests = addRequestPostProcessing(sortedRequests, analyzeQueueReason, analyzeCDN)
    const requestsWithConnections = assignConnectionNumbers(processedRequests)
    return requestsWithConnections
  }, [traceData])

  // Extract and process screenshots with SSIM analysis
  const [screenshots, setScreenshots] = useState<ScreenshotEvent[]>([])
  const [screenshotsLoading, setScreenshotsLoading] = useState(false)

  useEffect(() => {
    if (!traceData) {
      setScreenshots([])
      return
    }

    const processScreenshots = async () => {
      setScreenshotsLoading(true)
      try {
        const allScreenshots = extractScreenshots(traceData.traceEvents)
        console.log('Debug: Found screenshots:', allScreenshots.length)
        console.log('Debug: Screenshot events sample:', allScreenshots.slice(0, 3))
        
        const uniqueScreenshots = await findUniqueScreenshots(allScreenshots, ssimThreshold)
        console.log('Debug: Unique screenshots after SSIM analysis:', uniqueScreenshots.length)
        
        setScreenshots(uniqueScreenshots)
      } catch (error) {
        console.error('Error processing screenshots with SSIM:', error)
        // Fallback to extracting all screenshots without SSIM filtering
        const allScreenshots = extractScreenshots(traceData.traceEvents)
        setScreenshots(allScreenshots)
      } finally {
        setScreenshotsLoading(false)
      }
    }

    processScreenshots()
  }, [traceData, ssimThreshold])

  const filteredRequests = useMemo(() => {
    let requests = httpRequests

    // Filter by resource type
    if (resourceTypeFilter !== 'all') {
      requests = requests.filter(req => req.resourceType === resourceTypeFilter)
    }

    // Filter by protocol
    if (protocolFilter !== 'all') {
      requests = requests.filter(req => req.protocol === protocolFilter)
    }

    // Filter by hostname
    if (hostnameFilter !== 'all') {
      requests = requests.filter(req => req.hostname === hostnameFilter)
    }

    // Filter by priority
    if (priorityFilter !== 'all') {
      requests = requests.filter(req => req.priority === priorityFilter)
    }

    // Filter by search term
    if (searchTerm) {
      const term = searchTerm.toLowerCase()
      requests = requests.filter(req =>
        req.url.toLowerCase().includes(term) ||
        req.method.toLowerCase().includes(term) ||
        req.resourceType.toLowerCase().includes(term) ||
        req.hostname.toLowerCase().includes(term) ||
        req.statusCode?.toString().includes(term)
      )
    }

    return requests
  }, [httpRequests, resourceTypeFilter, protocolFilter, hostnameFilter, priorityFilter, searchTerm])

  const paginatedRequests = useMemo(() => {
    const startIndex = (currentPage - 1) * ITEMS_PER_PAGE
    return filteredRequests.slice(startIndex, startIndex + ITEMS_PER_PAGE)
  }, [filteredRequests, currentPage])

  // Create timeline entries that include both HTTP requests and screenshot changes
  const timelineEntries = useMemo(() => {
    const entries: Array<{ 
      type: 'request' | 'screenshot', 
      timestamp: number, 
      data: HTTPRequest | ScreenshotEvent 
    }> = []

    // Add HTTP requests
    filteredRequests.forEach(request => {
      entries.push({
        type: 'request',
        timestamp: request.timing.start,
        data: request
      })
    })

    // Add screenshots if enabled
    if (showScreenshots && screenshots.length > 0) {
      screenshots.forEach(screenshot => {
        entries.push({
          type: 'screenshot',
          timestamp: screenshot.timestamp,
          data: screenshot
        })
      })
    }

    // Sort by timestamp
    return entries.sort((a, b) => a.timestamp - b.timestamp)
  }, [filteredRequests, screenshots, showScreenshots])

  const paginatedTimelineEntries = useMemo(() => {
    const startIndex = (currentPage - 1) * ITEMS_PER_PAGE
    return timelineEntries.slice(startIndex, startIndex + ITEMS_PER_PAGE)
  }, [timelineEntries, currentPage])

  const resourceTypes = useMemo(() => {
    const types = new Set(httpRequests.map(req => req.resourceType))
    return Array.from(types).sort()
  }, [httpRequests])

  const protocols = useMemo(() => {
    const protos = new Set(httpRequests.map(req => req.protocol).filter((p): p is string => Boolean(p)))
    return Array.from(protos).sort()
  }, [httpRequests])

  const hostnames = useMemo(() => {
    const hosts = new Set(httpRequests.map(req => req.hostname).filter(h => h !== 'unknown'))
    return Array.from(hosts).sort()
  }, [httpRequests])

  const priorities = useMemo(() => {
    const prios = new Set(httpRequests.map(req => req.priority).filter(Boolean))
    return Array.from(prios).sort((a, b) => {
      // Sort priorities by importance: VeryHigh, High, Medium, Low, VeryLow
      const order = ['VeryHigh', 'High', 'Medium', 'Low', 'VeryLow']
      return order.indexOf(a) - order.indexOf(b)
    })
  }, [httpRequests])

  const totalPages = Math.ceil((showScreenshots ? timelineEntries.length : filteredRequests.length) / ITEMS_PER_PAGE)













  const toggleRowExpansion = (requestId: string) => {
    const newExpanded = new Set(expandedRows)
    if (newExpanded.has(requestId)) {
      newExpanded.delete(requestId)
    } else {
      newExpanded.add(requestId)
    }
    setExpandedRows(newExpanded)
  }

  const handleDownloadCSV = () => {
    const csvContent = exportRequestsToCSV(filteredRequests, {
      includeHeaders: true
    })
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5)
    const filename = `http-requests-${timestamp}.csv`
    downloadCSV(csvContent, filename)
  }


  if (loading) {
    return (
      <HTTPRequestLoading/>
    )
  }

  if (error) {
    return (
      <div className={styles.errorContainer}>
        <div className={styles.errorMessage}>
          <h3>Error Loading Trace Data</h3>
          <p>{error}</p>
        </div>
      </div>
    )
  }

  return (
    <div className={styles.container}>
      <h2>HTTP Requests & Responses</h2>
      {/* Controls */}
      <RequestFilters
        httpRequests={httpRequests}
        screenshots={screenshots}
        screenshotsLoading={screenshotsLoading}
        resourceTypes={resourceTypes}
        protocols={protocols}
        hostnames={hostnames}
        priorities={priorities}
        filteredRequests={filteredRequests}
        timelineEntries={timelineEntries}
        resourceTypeFilter={resourceTypeFilter}
        protocolFilter={protocolFilter}
        hostnameFilter={hostnameFilter}
        priorityFilter={priorityFilter}
        searchTerm={searchTerm}
        showQueueAnalysis={showQueueAnalysis}
        showScreenshots={showScreenshots}
        show3DViewer={show3DViewer}
        showTimelineViewer={showTimelineViewer}
        pendingSSIMThreshold={pendingSSIMThreshold}
        ssimThreshold={ssimThreshold}
        setResourceTypeFilter={setResourceTypeFilter}
        setProtocolFilter={setProtocolFilter}
        setHostnameFilter={setHostnameFilter}
        setPriorityFilter={setPriorityFilter}
        setSearchTerm={setSearchTerm}
        setCurrentPage={setCurrentPage}
        setShowQueueAnalysis={setShowQueueAnalysis}
        setShowScreenshots={setShowScreenshots}
        setShow3DViewer={handle3DViewerToggle}
        setShowTimelineViewer={handleTimelineViewerToggle}
        setPendingSSIMThreshold={setPendingSSIMThreshold}
        handleSSIMRecalculate={handleSSIMRecalculate}
      />

      {/* Export Controls */}
      <div className={styles.exportControls}>
        <button 
          onClick={handleDownloadCSV}
          className={styles.downloadButton}
          disabled={filteredRequests.length === 0}
        >
          📥 Download CSV ({filteredRequests.length} requests)
        </button>
      </div>

      <PaginationControls currentPage={currentPage} setCurrentPage={setCurrentPage} totalPages={totalPages} />

      {/* 3D Network Visualization Modal */}
      {show3DViewer && (
        <div className={styles.modalOverlay}>
          <div className={styles.modalContainer}>
            <div className={styles.modalHeader}>
              <h3 className={styles.modalTitle}>
                3D Network Visualization ({filteredRequests.length} requests)
              </h3>
              <button
                onClick={() => handle3DViewerToggle(false)}
                className={styles.modalCloseButton}
              >
                ✕ Close
              </button>
            </div>
            <div className={styles.modalContent}>
              <Suspense fallback={<ThreeDViewerLoading />}>
                <BabylonViewer httpRequests={filteredRequests} width={window.innerWidth * 0.9} height={window.innerHeight * 0.9 - 100} />
              </Suspense>
            </div>
            <div className={styles.modalLegend}>
              <div><strong>Legend:</strong></div>
              <div>⬛→⬜ Gray gradient: 2xx Success (darker=lower, lighter=higher)</div>
              <div>🟡 Yellow: 3xx Redirects</div>
              <div>🟠 Orange: 4xx Client Errors</div>
              <div>🔴 Red: 5xx Server Errors</div>
              <div><strong>Layout:</strong></div>
              <div>🔵 Central sphere: Origin</div>
              <div>🏷️ Hostname labels: At 12m radius</div>
              <div>📦 Request boxes: Start → end timeline</div>
              <div>📏 Front face: Request start time</div>
              <div>📐 Height: 0.1m-5m (content-length)</div>
              <div>📊 Depth: Request duration</div>
              <div>📚 Overlapping requests stack vertically</div>
              <div>🔗 Connection lines to center</div>
              <div>👁️ Labels always face camera</div>
            </div>
          </div>
        </div>
      )}

      {/* 3D Timeline Visualization Modal */}
      {showTimelineViewer && (
        <div className={styles.modalOverlay}>
          <div className={styles.modalContainer}>
            <div className={styles.modalHeader}>
              <h3 className={styles.modalTitle}>
                3D Timeline Visualization ({filteredRequests.length} requests)
              </h3>
              <button
                onClick={() => handleTimelineViewerToggle(false)}
                className={styles.modalCloseButton}
              >
                ✕ Close
              </button>
            </div>
            <div className={styles.modalContent}>
              <Suspense fallback={<ThreeDViewerLoading />}>
                <BabylonTimelineViewer httpRequests={filteredRequests} screenshots={screenshots} width={window.innerWidth * 0.9} height={window.innerHeight * 0.9 - 100} />
              </Suspense>
            </div>
            <div className={styles.modalLegend}>
              <div><strong>Legend:</strong></div>
              <div>⬛→⬜ Gray gradient: 2xx Success (darker=lower, lighter=higher)</div>
              <div>🟡 Yellow: 3xx Redirects</div>
              <div>🟠 Orange: 4xx Client Errors</div>
              <div>🔴 Red: 5xx Server Errors</div>
              <div><strong>Timeline Layout:</strong></div>
              <div>🔵 Central sphere: Timeline origin</div>
              <div>🏷️ Hostname labels: At 12m radius</div>
              <div>📦 Request boxes: Chronological timeline</div>
              <div>📏 Distance from center: Start time</div>
              <div>📐 Height: 0.1m-5m (content-length)</div>
              <div>📊 Depth: Request duration</div>
              <div>📚 Overlapping requests stack vertically</div>
              <div>🔗 Connection lines to center</div>
              <div>👁️ Labels face origin (180° rotated)</div>
            </div>
          </div>
        </div>
      )}

      {/* Column Settings */}
      <ColumnSettings
        visibleColumns={visibleColumns}
        onColumnToggle={handleColumnToggle}
        isOpen={columnSettingsOpen}
        onToggle={() => setColumnSettingsOpen(!columnSettingsOpen)}
        onShowAll={handleShowAllColumns}
        onHideAll={handleHideAllColumns}
        onResetDefaults={handleResetDefaults}
      />

      {/* Requests Table */}
      <RequestsTable
        httpRequests={httpRequests}
        showScreenshots={showScreenshots}
        paginatedTimelineEntries={paginatedTimelineEntries}
        paginatedRequests={paginatedRequests}
        showQueueAnalysis={showQueueAnalysis}
        expandedRows={expandedRows}
        onToggleRowExpansion={toggleRowExpansion}
        visibleColumns={visibleColumns}
      />
    </div>
  )
}