import { useMemo } from 'react'
import { useDatabaseTraceData } from '../hooks/useDatabaseTraceData'
import { processHTTPRequests } from './httprequestviewer/lib/httpRequestProcessor'
import { addRequestPostProcessing } from './httprequestviewer/lib/requestPostProcessor'
import { analyzeCDN, analyzeQueueReason } from './httprequestviewer/lib/analysisUtils'
import { assignConnectionNumbers } from './httprequestviewer/lib/connectionUtils'
import sortRequests from './httprequestviewer/lib/sortRequests'
import type { HTTPRequest } from './httprequestviewer/types/httpRequest'
import styles from './RequestBreakdown.module.css'

interface RequestBreakdownProps {
  traceId: string | null
}

interface BreakdownStats {
  totalRequests: number
  totalSize: number
  totalDuration: number
  averageResponseTime: number
  successRate: number
  cacheHitRate: number
}

interface CategoryBreakdown {
  name: string
  count: number
  percentage: number
  totalSize: number
  sizePercentage: number
  totalResponseTime: number
  responseTimePercentage: number
  averageResponseTime: number
}

const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
  const { traceData, loading, error } = useDatabaseTraceData(traceId)

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

  const overallStats: BreakdownStats = useMemo(() => {
    if (httpRequests.length === 0) {
      return {
        totalRequests: 0,
        totalSize: 0,
        totalDuration: 0,
        averageResponseTime: 0,
        successRate: 0,
        cacheHitRate: 0
      }
    }

    const totalSize = httpRequests.reduce((sum, req) => {
      const size = req.contentLength || req.encodedDataLength || 0
      return sum + size
    }, 0)

    const totalDuration = httpRequests.reduce((sum, req) => {
      return sum + (req.timing.duration || 0)
    }, 0)

    const totalResponseTime = httpRequests.reduce((sum, req) => {
      return sum + (req.timing.totalResponseTime || 0)
    }, 0)

    const successfulRequests = httpRequests.filter(req => 
      req.statusCode && req.statusCode >= 200 && req.statusCode < 300
    ).length

    const cachedRequests = httpRequests.filter(req => req.fromCache).length

    return {
      totalRequests: httpRequests.length,
      totalSize,
      totalDuration,
      averageResponseTime: totalResponseTime / httpRequests.length,
      successRate: (successfulRequests / httpRequests.length) * 100,
      cacheHitRate: (cachedRequests / httpRequests.length) * 100
    }
  }, [httpRequests])

  const resourceTypeBreakdown: CategoryBreakdown[] = useMemo(() => {
    const typeMap = new Map<string, HTTPRequest[]>()
    
    httpRequests.forEach(req => {
      const type = req.resourceType || 'unknown'
      if (!typeMap.has(type)) {
        typeMap.set(type, [])
      }
      typeMap.get(type)!.push(req)
    })

    // Calculate total size and response time across all requests for percentage calculations
    const totalAllSize = httpRequests.reduce((sum, req) => {
      return sum + (req.contentLength || req.encodedDataLength || 0)
    }, 0)

    const totalAllResponseTime = httpRequests.reduce((sum, req) => {
      return sum + (req.timing.totalResponseTime || 0)
    }, 0)

    return Array.from(typeMap.entries()).map(([type, requests]) => {
      const totalSize = requests.reduce((sum, req) => {
        return sum + (req.contentLength || req.encodedDataLength || 0)
      }, 0)
      
      const totalResponseTime = requests.reduce((sum, req) => {
        return sum + (req.timing.totalResponseTime || 0)
      }, 0)

      return {
        name: type,
        count: requests.length,
        percentage: (requests.length / httpRequests.length) * 100,
        totalSize,
        sizePercentage: totalAllSize > 0 ? (totalSize / totalAllSize) * 100 : 0,
        totalResponseTime,
        responseTimePercentage: totalAllResponseTime > 0 ? (totalResponseTime / totalAllResponseTime) * 100 : 0,
        averageResponseTime: totalResponseTime / requests.length
      }
    }).sort((a, b) => b.count - a.count)
  }, [httpRequests])

  const statusCodeBreakdown: CategoryBreakdown[] = useMemo(() => {
    const statusMap = new Map<string, HTTPRequest[]>()
    
    httpRequests.forEach(req => {
      const status = req.statusCode ? Math.floor(req.statusCode / 100) + 'xx' : 'Unknown'
      if (!statusMap.has(status)) {
        statusMap.set(status, [])
      }
      statusMap.get(status)!.push(req)
    })

    // Calculate total size and response time across all requests for percentage calculations
    const totalAllSize = httpRequests.reduce((sum, req) => {
      return sum + (req.contentLength || req.encodedDataLength || 0)
    }, 0)

    const totalAllResponseTime = httpRequests.reduce((sum, req) => {
      return sum + (req.timing.totalResponseTime || 0)
    }, 0)

    return Array.from(statusMap.entries()).map(([status, requests]) => {
      const totalSize = requests.reduce((sum, req) => {
        return sum + (req.contentLength || req.encodedDataLength || 0)
      }, 0)
      
      const totalResponseTime = requests.reduce((sum, req) => {
        return sum + (req.timing.totalResponseTime || 0)
      }, 0)

      return {
        name: status,
        count: requests.length,
        percentage: (requests.length / httpRequests.length) * 100,
        totalSize,
        sizePercentage: totalAllSize > 0 ? (totalSize / totalAllSize) * 100 : 0,
        totalResponseTime,
        responseTimePercentage: totalAllResponseTime > 0 ? (totalResponseTime / totalAllResponseTime) * 100 : 0,
        averageResponseTime: totalResponseTime / requests.length
      }
    }).sort((a, b) => b.count - a.count)
  }, [httpRequests])

  const hostnameBreakdown: CategoryBreakdown[] = useMemo(() => {
    const hostMap = new Map<string, HTTPRequest[]>()
    
    httpRequests.forEach(req => {
      const hostname = req.hostname || 'unknown'
      if (!hostMap.has(hostname)) {
        hostMap.set(hostname, [])
      }
      hostMap.get(hostname)!.push(req)
    })

    // Calculate total size and response time across all requests for percentage calculations
    const totalAllSize = httpRequests.reduce((sum, req) => {
      return sum + (req.contentLength || req.encodedDataLength || 0)
    }, 0)

    const totalAllResponseTime = httpRequests.reduce((sum, req) => {
      return sum + (req.timing.totalResponseTime || 0)
    }, 0)

    return Array.from(hostMap.entries()).map(([hostname, requests]) => {
      const totalSize = requests.reduce((sum, req) => {
        return sum + (req.contentLength || req.encodedDataLength || 0)
      }, 0)
      
      const totalResponseTime = requests.reduce((sum, req) => {
        return sum + (req.timing.totalResponseTime || 0)
      }, 0)

      return {
        name: hostname,
        count: requests.length,
        percentage: (requests.length / httpRequests.length) * 100,
        totalSize,
        sizePercentage: totalAllSize > 0 ? (totalSize / totalAllSize) * 100 : 0,
        totalResponseTime,
        responseTimePercentage: totalAllResponseTime > 0 ? (totalResponseTime / totalAllResponseTime) * 100 : 0,
        averageResponseTime: totalResponseTime / requests.length
      }
    }).sort((a, b) => b.count - a.count)
  }, [httpRequests])

  const formatSize = (bytes: number): string => {
    if (bytes < 1024) return `${bytes} B`
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
    return `${(bytes / 1024 / 1024).toFixed(1)} MB`
  }

  const formatDuration = (microseconds: number): string => {
    if (microseconds < 1000) return `${microseconds.toFixed(0)} μs`
    if (microseconds < 1000000) return `${(microseconds / 1000).toFixed(1)} ms`
    return `${(microseconds / 1000000).toFixed(2)} s`
  }

  if (loading) {
    return (
      <div className={styles.container}>
        <div className={styles.loading}>Loading request breakdown...</div>
      </div>
    )
  }

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

  return (
    <div className={styles.container}>
      <h2>Request Data Breakdown</h2>
      
      {/* Overall Stats */}
      <div className={styles.statsGrid}>
        <div className={styles.statCard}>
          <h3>Total Requests</h3>
          <div className={styles.statValue}>{overallStats.totalRequests}</div>
        </div>
        <div className={styles.statCard}>
          <h3>Total Size</h3>
          <div className={styles.statValue}>{formatSize(overallStats.totalSize)}</div>
        </div>
        <div className={styles.statCard}>
          <h3>Average Response Time</h3>
          <div className={styles.statValue}>{formatDuration(overallStats.averageResponseTime)}</div>
        </div>
        <div className={styles.statCard}>
          <h3>Success Rate</h3>
          <div className={styles.statValue}>{overallStats.successRate.toFixed(1)}%</div>
        </div>
        <div className={styles.statCard}>
          <h3>Cache Hit Rate</h3>
          <div className={styles.statValue}>{overallStats.cacheHitRate.toFixed(1)}%</div>
        </div>
      </div>

      {/* Resource Type Breakdown */}
      <div className={styles.breakdownSection}>
        <h3>By Resource Type</h3>
        <div className={styles.breakdownTable}>
          <div className={styles.tableHeader}>
            <span>Type</span>
            <span>Count</span>
            <span>Count %</span>
            <span>Total Size</span>
            <span>Size %</span>
            <span>Total Response Time</span>
            <span>Response Time %</span>
            <span>Avg Response Time</span>
          </div>
          {resourceTypeBreakdown.map(item => (
            <div key={item.name} className={styles.tableRow}>
              <span className={styles.categoryName}>{item.name}</span>
              <span>{item.count}</span>
              <div className={styles.percentageCell}>
                <span>{item.percentage.toFixed(1)}%</span>
                <div className={styles.progressBar}>
                  <div 
                    className={styles.progressFill}
                    style={{ width: `${item.percentage}%` }}
                  ></div>
                </div>
              </div>
              <span>{formatSize(item.totalSize)}</span>
              <div className={styles.percentageCell}>
                <span>{item.sizePercentage.toFixed(1)}%</span>
                <div className={styles.progressBar}>
                  <div 
                    className={styles.progressFill}
                    style={{ width: `${item.sizePercentage}%` }}
                  ></div>
                </div>
              </div>
              <span>{formatDuration(item.totalResponseTime)}</span>
              <div className={styles.percentageCell}>
                <span>{item.responseTimePercentage.toFixed(1)}%</span>
                <div className={styles.progressBar}>
                  <div 
                    className={styles.progressFill}
                    style={{ width: `${item.responseTimePercentage}%` }}
                  ></div>
                </div>
              </div>
              <span>{formatDuration(item.averageResponseTime)}</span>
            </div>
          ))}
        </div>
      </div>

      {/* Status Code Breakdown */}
      <div className={styles.breakdownSection}>
        <h3>By Status Code</h3>
        <div className={styles.breakdownTable}>
          <div className={styles.tableHeader}>
            <span>Status</span>
            <span>Count</span>
            <span>Count %</span>
            <span>Total Size</span>
            <span>Size %</span>
            <span>Total Response Time</span>
            <span>Response Time %</span>
            <span>Avg Response Time</span>
          </div>
          {statusCodeBreakdown.map(item => (
            <div key={item.name} className={styles.tableRow}>
              <span className={styles.categoryName}>{item.name}</span>
              <span>{item.count}</span>
              <div className={styles.percentageCell}>
                <span>{item.percentage.toFixed(1)}%</span>
                <div className={styles.progressBar}>
                  <div 
                    className={styles.progressFill}
                    style={{ width: `${item.percentage}%` }}
                  ></div>
                </div>
              </div>
              <span>{formatSize(item.totalSize)}</span>
              <div className={styles.percentageCell}>
                <span>{item.sizePercentage.toFixed(1)}%</span>
                <div className={styles.progressBar}>
                  <div 
                    className={styles.progressFill}
                    style={{ width: `${item.sizePercentage}%` }}
                  ></div>
                </div>
              </div>
              <span>{formatDuration(item.totalResponseTime)}</span>
              <div className={styles.percentageCell}>
                <span>{item.responseTimePercentage.toFixed(1)}%</span>
                <div className={styles.progressBar}>
                  <div 
                    className={styles.progressFill}
                    style={{ width: `${item.responseTimePercentage}%` }}
                  ></div>
                </div>
              </div>
              <span>{formatDuration(item.averageResponseTime)}</span>
            </div>
          ))}
        </div>
      </div>

      {/* Hostname Breakdown */}
      <div className={styles.breakdownSection}>
        <h3>By Hostname</h3>
        <div className={styles.breakdownTable}>
          <div className={styles.tableHeader}>
            <span>Hostname</span>
            <span>Count</span>
            <span>Count %</span>
            <span>Total Size</span>
            <span>Size %</span>
            <span>Total Response Time</span>
            <span>Response Time %</span>
            <span>Avg Response Time</span>
          </div>
          {hostnameBreakdown.slice(0, 10).map(item => (
            <div key={item.name} className={styles.tableRow}>
              <span className={styles.categoryName}>{item.name}</span>
              <span>{item.count}</span>
              <div className={styles.percentageCell}>
                <span>{item.percentage.toFixed(1)}%</span>
                <div className={styles.progressBar}>
                  <div 
                    className={styles.progressFill}
                    style={{ width: `${item.percentage}%` }}
                  ></div>
                </div>
              </div>
              <span>{formatSize(item.totalSize)}</span>
              <div className={styles.percentageCell}>
                <span>{item.sizePercentage.toFixed(1)}%</span>
                <div className={styles.progressBar}>
                  <div 
                    className={styles.progressFill}
                    style={{ width: `${item.sizePercentage}%` }}
                  ></div>
                </div>
              </div>
              <span>{formatDuration(item.totalResponseTime)}</span>
              <div className={styles.percentageCell}>
                <span>{item.responseTimePercentage.toFixed(1)}%</span>
                <div className={styles.progressBar}>
                  <div 
                    className={styles.progressFill}
                    style={{ width: `${item.responseTimePercentage}%` }}
                  ></div>
                </div>
              </div>
              <span>{formatDuration(item.averageResponseTime)}</span>
            </div>
          ))}
        </div>
        {hostnameBreakdown.length > 10 && (
          <div className={styles.moreInfo}>
            Showing top 10 of {hostnameBreakdown.length} hostnames
          </div>
        )}
      </div>
    </div>
  )
}

export default RequestBreakdown