import type { TraceEvent } from '../../../types/trace'
import type { JavaScriptEvent, JavaScriptSummary } from '../types/javascriptEvent'

// JavaScript event names we're interested in
const JS_EVENT_NAMES = [
  'EvaluateScript',
  'v8.compile',
  'v8.callFunction',
  'v8.newInstance',
  'V8.DeoptimizeAllOptimizedCodeWithFunction',
  'CpuProfiler::StartProfiling',
  'ScriptCatchup'
] as const

export const processJavaScriptEvents = (traceEvents: TraceEvent[]): JavaScriptEvent[] => {
  const jsEvents: JavaScriptEvent[] = []
  
  for (const event of traceEvents) {
    // Filter for JavaScript-related events
    if (!JS_EVENT_NAMES.includes(event.name as any)) {
      continue
    }
    
    // Skip events without timing data
    if (!event.dur && !event.ts) {
      continue
    }
    
    const args = event.args as any
    const eventId = `${event.name}-${event.ts}-${event.tid}`
    
    // Extract URL and script information
    let url = ''
    let fileName = ''
    let lineNumber: number | undefined
    let columnNumber: number | undefined
    let isInlineScript = false
    
    if (args?.data?.url) {
      url = args.data.url
      fileName = args.fileName || url
      isInlineScript = args.data.notStreamedReason === 'inline script' || !url.startsWith('http')
    } else if (args?.fileName) {
      fileName = args.fileName
      url = fileName
    }
    
    if (args?.data?.lineNumber !== undefined) {
      lineNumber = args.data.lineNumber
    }
    if (args?.data?.columnNumber !== undefined) {
      columnNumber = args.data.columnNumber
    }
    
    const duration = event.dur || 0
    
    const jsEvent: JavaScriptEvent = {
      eventId,
      name: event.name,
      category: event.cat || '',
      url,
      fileName,
      lineNumber,
      columnNumber,
      isInlineScript,
      scriptId: args?.data?.scriptId?.toString(),
      sampleTraceId: args?.data?.sampleTraceId?.toString(),
      
      timing: {
        startTime: event.ts,
        duration,
        threadDuration: event.tdur,
        durationMs: duration / 1000 // Convert to milliseconds
      },
      
      v8Data: {
        streamed: args?.data?.streamed,
        notStreamedReason: args?.data?.notStreamedReason,
        isolate: args?.data?.isolate?.toString(),
        executionContextId: args?.data?.executionContextId
      },
      
      rawEvent: event
    }
    
    jsEvents.push(jsEvent)
  }
  
  // Sort by start time
  return jsEvents.sort((a, b) => a.timing.startTime - b.timing.startTime)
}

export const calculateJavaScriptSummary = (events: JavaScriptEvent[]): JavaScriptSummary => {
  let totalExecutionTime = 0
  let totalCompilationTime = 0 
  let totalEvaluationTime = 0
  
  const eventsByType = {
    compilation: 0,
    evaluation: 0,
    execution: 0,
    other: 0
  }
  
  const scriptsByUrl = new Map<string, {
    url: string
    events: JavaScriptEvent[]
    totalTime: number
    isThirdParty: boolean
  }>()
  
  for (const event of events) {
    // Categorize by event type
    if (event.name === 'v8.compile') {
      totalCompilationTime += event.timing.duration
      eventsByType.compilation++
    } else if (event.name === 'EvaluateScript') {
      totalEvaluationTime += event.timing.duration
      eventsByType.evaluation++
    } else if (event.name.includes('callFunction') || event.name.includes('newInstance')) {
      totalExecutionTime += event.timing.duration
      eventsByType.execution++
    } else {
      eventsByType.other++
    }
    
    // Group by URL/script
    if (event.url) {
      const url = event.isInlineScript ? '(inline scripts)' : event.url
      const isThirdParty = event.url.startsWith('http') && 
                          !event.url.includes(window.location?.hostname || 'localhost')
      
      if (!scriptsByUrl.has(url)) {
        scriptsByUrl.set(url, {
          url,
          events: [],
          totalTime: 0,
          isThirdParty
        })
      }
      
      const script = scriptsByUrl.get(url)!
      script.events.push(event)
      script.totalTime += event.timing.duration
    }
  }
  
  return {
    totalEvents: events.length,
    totalExecutionTime: totalExecutionTime + totalCompilationTime + totalEvaluationTime,
    totalCompilationTime,
    totalEvaluationTime,
    eventsByType,
    scriptsByUrl
  }
}