import type { TraceFile } from '../../types/trace'

/**
 * Loads and parses the trace.json file from the public directory with streaming support
 * @returns Promise that resolves to the parsed trace data
 */
export async function loadTraceFile(): Promise<TraceFile> {
  try {
    const response = await fetch('/trace.json')
    
    if (!response.ok) {
      throw new Error(`Failed to load trace.json: ${response.status} ${response.statusText}`)
    }
    
    // Get the response as text first to avoid JSON.parse call stack issues
    const textData = await response.text()
    
    // Parse JSON with error handling for large files
    let traceData: TraceFile
    try {
      // Use a timeout to prevent blocking the main thread too long
      traceData = await parseJSONSafely(textData)
    } catch (parseError) {
      throw new Error(`Failed to parse trace JSON: ${parseError}`)
    }
    
    // Basic validation to ensure the structure matches our expected format
    if (!traceData.metadata || !Array.isArray(traceData.traceEvents)) {
      throw new Error('Invalid trace file format: missing metadata or traceEvents array')
    }
    
    return traceData
  } catch (error) {
    console.error('Error loading trace file:', error)
    throw error
  }
}

/**
 * Safely parse JSON with chunked processing to avoid call stack issues
 */
async function parseJSONSafely(jsonString: string): Promise<TraceFile> {
  return new Promise((resolve, reject) => {
    // Use setTimeout to prevent blocking the main thread
    setTimeout(() => {
      try {
        const parsed = JSON.parse(jsonString)
        resolve(parsed)
      } catch (error) {
        reject(error)
      }
    }, 0)
  })
}

/**
 * Loads trace file with error handling and loading state management
 * Useful for React components that need loading states
 */
export async function loadTraceFileWithStatus(): Promise<{
  data: TraceFile | null
  loading: boolean
  error: string | null
}> {
  try {
    const data = await loadTraceFile()
    return {
      data,
      loading: false,
      error: null
    }
  } catch (error) {
    return {
      data: null,
      loading: false,
      error: error instanceof Error ? error.message : 'Unknown error occurred'
    }
  }
}

/**
 * Utility function to get basic trace statistics with optimized processing for large datasets
 * @param traceData - The loaded trace data
 * @returns Object containing basic statistics about the trace
 */
export function getTraceStats(traceData: TraceFile) {
  const { traceEvents, metadata } = traceData
  
  // Initialize counters
  const eventsByPhase: Record<string, number> = {}
  const processes = new Set<number>()
  const threads = new Set<string>()
  let minTimestamp = Infinity
  let maxTimestamp = -Infinity
  
  // Single pass through events to calculate all stats efficiently
  for (const event of traceEvents) {
    // Count phase types
    eventsByPhase[event.ph] = (eventsByPhase[event.ph] || 0) + 1
    
    // Track processes and threads
    processes.add(event.pid)
    threads.add(`${event.pid}:${event.tid}`)
    
    // Track time range (only for events with valid timestamps)
    if (event.ts > 0) {
      minTimestamp = Math.min(minTimestamp, event.ts)
      maxTimestamp = Math.max(maxTimestamp, event.ts)
    }
  }
  
  // Handle case where no valid timestamps were found
  if (minTimestamp === Infinity) {
    minTimestamp = 0
    maxTimestamp = 0
  }
  
  const duration = maxTimestamp - minTimestamp
  
  return {
    totalEvents: traceEvents.length,
    eventsByPhase,
    timeRange: {
      start: minTimestamp,
      end: maxTimestamp,
      duration: duration
    },
    processCount: processes.size,
    threadCount: threads.size,
    metadata: {
      source: metadata.source,
      startTime: metadata.startTime,
      hardwareConcurrency: metadata.hardwareConcurrency
    }
  }
}