import type { HTTPRequest, CDNAnalysis, QueueAnalysis } from '../types/httpRequest'
import { HIGHLIGHTING_CONFIG } from './httpRequestConstants'

export const analyzeCDN = (request: HTTPRequest): CDNAnalysis => {
  const hostname = request.hostname.toLowerCase()
  const headers = request.responseHeaders || []
  const headerMap = new Map(headers.map(h => [h.name.toLowerCase(), h.value.toLowerCase()]))
  
  let provider: CDNAnalysis['provider'] = 'unknown'
  let isEdge = false
  let cacheStatus: CDNAnalysis['cacheStatus'] = 'unknown'
  let edgeLocation: string | undefined
  let confidence = 0
  let detectionMethod = 'unknown'

  // Enhanced Akamai detection (check this first as it's often missed)
  if (headerMap.has('akamai-cache-status') || 
      headerMap.has('x-cache-key') ||
      headerMap.has('x-akamai-request-id') ||
      headerMap.has('x-akamai-edgescape') ||
      headerMap.get('server')?.includes('akamai') ||
      headerMap.get('server')?.includes('akamainet') ||
      headerMap.get('server')?.includes('akamainetworking') ||
      headerMap.get('x-cache')?.includes('akamai') ||
      hostname.includes('akamai') ||
      hostname.includes('akamaized') ||
      hostname.includes('akamaicdn') ||
      hostname.includes('akamai-staging') ||
      // Check for Akamai Edge hostnames patterns
      /e\d+\.a\.akamaiedge\.net/.test(hostname) ||
      // Check Via header for Akamai
      headerMap.get('via')?.includes('akamai') ||
      // Check for Akamai Image Manager server header
      (headerMap.get('server') === 'akamai image manager') ||
      // Check for typical Akamai headers
      headerMap.has('x-serial') ||
      // Additional Akamai detection patterns
      headerMap.has('x-akamai-session-info') ||
      headerMap.has('x-akamai-ssl-client-sid') ||
      headerMap.get('x-cache')?.includes('tcp_hit') ||
      headerMap.get('x-cache')?.includes('tcp_miss') ||
      // Akamai sometimes uses x-served-by with specific patterns
      (headerMap.has('x-served-by') && headerMap.get('x-served-by')?.includes('cache-'))) {
    provider = 'akamai'
    confidence = 0.95
    detectionMethod = 'enhanced akamai detection (headers/hostname/server)'
    isEdge = true
    
    const akamaiStatus = headerMap.get('akamai-cache-status')
    if (akamaiStatus) {
      if (akamaiStatus.includes('hit')) cacheStatus = 'hit'
      else if (akamaiStatus.includes('miss')) cacheStatus = 'miss'
    }
    
    // Also check x-cache for Akamai cache status
    const xCache = headerMap.get('x-cache')
    if (xCache && !akamaiStatus) {
      if (xCache.includes('hit')) cacheStatus = 'hit'
      else if (xCache.includes('miss')) cacheStatus = 'miss'
      else if (xCache.includes('tcp_hit')) cacheStatus = 'hit'
      else if (xCache.includes('tcp_miss')) cacheStatus = 'miss'
    }
  }
  
  // Cloudflare detection
  else if (headerMap.has('cf-ray') || headerMap.has('cf-cache-status') || hostname.includes('cloudflare')) {
    provider = 'cloudflare'
    confidence = 0.95
    detectionMethod = 'headers (cf-ray/cf-cache-status)'
    isEdge = true
    
    const cfCacheStatus = headerMap.get('cf-cache-status')
    if (cfCacheStatus) {
      if (cfCacheStatus.includes('hit')) cacheStatus = 'hit'
      else if (cfCacheStatus.includes('miss')) cacheStatus = 'miss'
      else if (cfCacheStatus.includes('expired')) cacheStatus = 'expired'
      else if (cfCacheStatus.includes('bypass')) cacheStatus = 'bypass'
    }
    
    edgeLocation = headerMap.get('cf-ray')?.split('-')[1]
  }
  
  // AWS CloudFront detection  
  else if (headerMap.has('x-amz-cf-id') || headerMap.has('x-amz-cf-pop') || 
           hostname.includes('cloudfront.net')) {
    provider = 'aws_cloudfront'
    confidence = 0.95
    detectionMethod = 'headers (x-amz-cf-id/x-amz-cf-pop)'
    isEdge = true
    
    const cloudfrontCache = headerMap.get('x-cache')
    if (cloudfrontCache) {
      if (cloudfrontCache.includes('hit')) cacheStatus = 'hit'
      else if (cloudfrontCache.includes('miss')) cacheStatus = 'miss'
    }
    
    edgeLocation = headerMap.get('x-amz-cf-pop')
  }
  
  // Fastly detection (moved after Akamai to avoid false positives)
  else if (headerMap.has('fastly-debug-digest') || 
           headerMap.has('fastly-debug-path') ||
           hostname.includes('fastly.com') || 
           hostname.includes('fastlylb.net') ||
           headerMap.get('via')?.includes('fastly') ||
           headerMap.get('x-cache')?.includes('fastly') ||
           // Only use x-served-by for Fastly if it has specific Fastly patterns
           (headerMap.has('x-served-by') && (
             headerMap.get('x-served-by')?.includes('fastly') ||
             headerMap.get('x-served-by')?.includes('f1') ||
             headerMap.get('x-served-by')?.includes('f2')
           ))) {
    provider = 'fastly'
    confidence = 0.85
    detectionMethod = 'headers (fastly-debug-digest/via/x-cache)'
    isEdge = true
    
    const fastlyCache = headerMap.get('x-cache')
    if (fastlyCache) {
      if (fastlyCache.includes('hit')) cacheStatus = 'hit'
      else if (fastlyCache.includes('miss')) cacheStatus = 'miss'
    }
  }
  
  // Azure CDN detection
  else if (headerMap.has('x-azure-ref') || hostname.includes('azureedge.net')) {
    provider = 'azure_cdn'
    confidence = 0.9
    detectionMethod = 'headers (x-azure-ref) or hostname'
    isEdge = true
  }
  
  // Google CDN detection
  else if (headerMap.has('x-goog-generation') || hostname.includes('googleapis.com') ||
           headerMap.get('server')?.includes('gws')) {
    provider = 'google_cdn'
    confidence = 0.8
    detectionMethod = 'headers (x-goog-generation) or server'
    isEdge = true
  }
  
  // Generic CDN patterns
  else if (hostname.includes('cdn') || hostname.includes('cache') || 
           hostname.includes('edge') || hostname.includes('static')) {
    provider = 'unknown'
    confidence = 0.3
    detectionMethod = 'hostname patterns (cdn/cache/edge/static)'
    isEdge = true
  }

  // Check for origin indicators (lower confidence for edge)
  if (hostname.includes('origin') || hostname.includes('api') || 
      headerMap.get('x-cache')?.includes('miss from origin')) {
    isEdge = false
    confidence = Math.max(0.1, confidence - 0.2)
    detectionMethod += ' + origin indicators'
  }

  return {
    provider,
    isEdge,
    cacheStatus,
    edgeLocation,
    confidence,
    detectionMethod
  }
}

export const analyzeQueueReason = (request: HTTPRequest, allRequests: HTTPRequest[]): QueueAnalysis => {
  const queueTime = request.timing.queueTime || 0
  
  // If no significant queue time, no analysis needed
  if (queueTime < HIGHLIGHTING_CONFIG.QUEUE_TIME.ANALYSIS_THRESHOLD) {
    return {
      reason: 'unknown',
      description: 'No significant queueing detected',
      concurrentRequests: 0
    }
  }

  const requestStart = request.timing.start
  const requestEnd = request.timing.end || requestStart + (request.timing.duration || 0)
  
  // Find concurrent requests to the same host
  const concurrentToSameHost = allRequests.filter(other => {
    if (other.requestId === request.requestId) return false
    if (other.hostname !== request.hostname) return false
    
    const otherStart = other.timing.start
    const otherEnd = other.timing.end || otherStart + (other.timing.duration || 0)
    
    // Check if requests overlap in time
    return (otherStart <= requestEnd && otherEnd >= requestStart)
  })

  const concurrentSameProtocol = concurrentToSameHost.filter(r => r.protocol === request.protocol)
  
  // HTTP/1.1 connection limit analysis (typically 6 connections per host)
  if (request.protocol === 'http/1.1' && concurrentSameProtocol.length >= 6) {
    return {
      reason: 'connection_limit',
      description: `HTTP/1.1 connection limit reached (${concurrentSameProtocol.length} concurrent requests)`,
      concurrentRequests: concurrentSameProtocol.length,
      relatedRequests: concurrentSameProtocol.slice(0, 5).map(r => r.requestId)
    }
  }

  // H2 multiplexing but still queued - likely priority or server limits
  if (request.protocol === 'h2' && concurrentSameProtocol.length > 0) {
    // Check if lower priority requests are being processed first
    const lowerPriorityActive = concurrentSameProtocol.filter(r => {
      const priorityOrder = ['VeryLow', 'Low', 'Medium', 'High', 'VeryHigh']
      const requestPriorityIndex = priorityOrder.indexOf(request.priority || 'Medium')
      const otherPriorityIndex = priorityOrder.indexOf(r.priority || 'Medium')
      return otherPriorityIndex < requestPriorityIndex
    })

    if (lowerPriorityActive.length > 0) {
      return {
        reason: 'priority_queue',
        description: `Queued behind ${lowerPriorityActive.length} lower priority requests`,
        concurrentRequests: concurrentSameProtocol.length,
        relatedRequests: lowerPriorityActive.slice(0, 3).map(r => r.requestId)
      }
    }

    return {
      reason: 'resource_contention',
      description: `Server resource contention (${concurrentSameProtocol.length} concurrent H2 requests)`,
      concurrentRequests: concurrentSameProtocol.length,
      relatedRequests: concurrentSameProtocol.slice(0, 3).map(r => r.requestId)
    }
  }

  // General resource contention
  if (concurrentToSameHost.length > 0) {
    return {
      reason: 'resource_contention',
      description: `Resource contention with ${concurrentToSameHost.length} concurrent requests`,
      concurrentRequests: concurrentToSameHost.length,
      relatedRequests: concurrentToSameHost.slice(0, 3).map(r => r.requestId)
    }
  }

  return {
    reason: 'unknown',
    description: `Queued for ${(queueTime / 1000).toFixed(1)}ms - reason unclear`,
    concurrentRequests: 0
  }
}