import addTimingToRequest from "./addTimingToRequest.ts";
import type {HTTPRequest} from "../types/httpRequest.ts";

export default function sortRequests(httpRequests: HTTPRequest[]): HTTPRequest[] {
    return httpRequests
        .map(request => {
            // Calculate queue time using Chrome DevTools methodology
            if (request.events.receiveResponse) {
                const responseArgs = request.events.receiveResponse.args as any
                const timingData = responseArgs?.data?.timing

                if (timingData?.requestTime && timingData?.sendStart !== undefined) {
                    const sendStartUs = timingData.sendStart * 1000

                    request.timing.queueTime = sendStartUs // This is queuing + DNS + connection time
                    addTimingToRequest(request, timingData);

                    if (request.events.sendRequest) {
                        const requestTimeUs = timingData.requestTime * 1000000
                        const resourceSendRequestTs = request.events.sendRequest.ts
                        const chromeInternalDelay = requestTimeUs - resourceSendRequestTs

                        // If there's a significant delay (>1ms) between trace event and timing baseline
                        if (chromeInternalDelay > 1000) {
                            // Total queue time = Chrome internal delay + network queue time
                            request.timing.queueTime = chromeInternalDelay + sendStartUs
                        } else {
                            // For more accurate Chrome DevTools matching when no significant delay
                            if (timingData.dnsStart >= 0 && timingData.connectStart >= 0) {
                                // If we have detailed timing, isolate just the queuing portion
                                const dnsStartUs = timingData.dnsStart * 1000
                                request.timing.queueTime = dnsStartUs // Pure queuing before DNS
                            } else if (timingData.connectStart >= 0) {
                                // If no DNS timing but have connection timing
                                const connectStartUs = timingData.connectStart * 1000
                                request.timing.queueTime = connectStartUs // Queuing before connection
                            } else {
                                // Default: use sendStart as queue time
                                request.timing.queueTime = sendStartUs
                            }
                        }
                    } else {
                        // Fallback when no ResourceSendRequest event
                        request.timing.queueTime = sendStartUs
                    }
                } else if (request.events.willSendRequest && request.events.sendRequest) {
                    // Legacy fallback: ResourceSendRequest - ResourceWillSendRequest
                    request.timing.queueTime = request.events.sendRequest.ts - request.events.willSendRequest.ts
                }
            } else if (request.events.willSendRequest && request.events.sendRequest) {
                // Final fallback when no timing data available
                request.timing.queueTime = request.events.sendRequest.ts - request.events.willSendRequest.ts
            }

            // Calculate server latency from network timing data - matching Chrome DevTools methodology
            if (request.events.receiveResponse) {
                const responseArgs = request.events.receiveResponse.args as any
                const timingData = responseArgs?.data?.timing

                if (timingData) {
                    // Chrome DevTools "Waiting (TTFB)" = Time to First Byte
                    // This is sendEnd to receiveHeadersStart (time server takes to process and respond)
                    if (timingData.receiveHeadersStart !== undefined && timingData.sendEnd !== undefined) {
                        // Standard method: sendEnd to receiveHeadersStart (server processing time)
                        request.timing.serverLatency = (timingData.receiveHeadersStart - timingData.sendEnd) * 1000 // Convert to microseconds
                    } else if (timingData.receiveHeadersStart !== undefined && timingData.sendStart !== undefined) {
                        // Fallback: sendStart to receiveHeadersStart (includes send time + server processing)
                        request.timing.serverLatency = (timingData.receiveHeadersStart - timingData.sendStart) * 1000
                    }

                    // Ensure non-negative values
                    if (request.timing.serverLatency && request.timing.serverLatency < 0) {
                        request.timing.serverLatency = 0
                    }
                }
            }

            // Fallback calculation if detailed timing not available
            if (!request.timing.serverLatency && request.timing.duration && request.timing.queueTime) {
                // This is an approximation - actual server latency would need more detailed timing
                request.timing.serverLatency = Math.max(0, request.timing.duration - request.timing.queueTime)
            }

            return request
        })
        .sort((a, b) => a.timing.start - b.timing.start);
}