import Foundation

/// Network interceptor using URLProtocol for automatic capture
public final class NetworkInterceptor: URLProtocol {
    public static var onRequest: ((DiagnosticsNetworkRequest) -> Void)?
    private static let shared = NetworkInterceptor()
    private var requestId: String?
    private var startTime: Date?
    private var request: URLRequest?
    
    private lazy var session: URLSession = {
        let config = URLSessionConfiguration.default
        return URLSession(configuration: config, delegate: self, delegateQueue: nil)
    }()
    
    private var dataTask: URLSessionDataTask?
    
    // MARK: - URLProtocol Overrides
    
    public override class func canInit(with request: URLRequest) -> Bool {
        // Don't intercept our own requests
        if request.value(forHTTPHeaderField: "X-Diagnostics-Intercepted") != nil {
            return false
        }
        return true
    }
    
    public override class func canonicalRequest(for request: URLRequest) -> URLRequest {
        return request
    }
    
    public override func startLoading() {
        requestId = "\(Int(Date().timeIntervalSince1970 * 1000))_\(UUID().uuidString.prefix(7))"
        startTime = Date()
        
        var newRequest = request
        newRequest?.setValue("true", forHTTPHeaderField: "X-Diagnostics-Intercepted")
        
        self.request = newRequest
        
        dataTask = session.dataTask(with: newRequest!)
        dataTask?.resume()
    }
    
    public override func stopLoading() {
        dataTask?.cancel()
    }
    
    // MARK: - Public API
    
    public static func start() {
        URLProtocol.registerClass(NetworkInterceptor.self)
    }
    
    public static func stop() {
        URLProtocol.unregisterClass(NetworkInterceptor.self)
    }
    
    public func start(with handler: @escaping (DiagnosticsNetworkRequest) -> Void) {
        NetworkInterceptor.onRequest = handler
        NetworkInterceptor.start()
    }
    
    public func stopInterceptor() {
        NetworkInterceptor.stop()
        NetworkInterceptor.onRequest = nil
    }
}

// MARK: - URLSessionDataDelegate

extension NetworkInterceptor: URLSessionDataDelegate {
    public func urlSession(
        _ session: URLSession,
        dataTask: URLSessionDataTask,
        didReceive data: Data
    ) {
        client?.urlProtocol(self, didLoad: data)
    }
    
    public func urlSession(
        _ session: URLSession,
        task: URLSessionTask,
        didCompleteWithError error: Error?
    ) {
        guard let request = request,
              let requestId = requestId,
              let startTime = startTime else {
            return
        }
        
        let endTime = Date()
        let durationMs = endTime.timeIntervalSince(startTime) * 1000
        
        var networkRequest = DiagnosticsNetworkRequest(
            id: requestId,
            url: request.url?.absoluteString ?? "",
            method: request.httpMethod ?? "GET",
            requestHeaders: request.allHTTPHeaderFields?.mapValues { value in
                NetworkInterceptor.sanitizeHeader(value, key: "")
            } ?? [:],
            requestBody: request.httpBody.flatMap { String(data: $0, encoding: .utf8) },
            startTime: ISO8601DateFormatter().string(from: startTime),
            endTime: ISO8601DateFormatter().string(from: endTime),
            durationMs: durationMs
        )
        
        if let error = error {
            networkRequest = DiagnosticsNetworkRequest(
                id: requestId,
                url: networkRequest.url,
                method: networkRequest.method,
                requestHeaders: networkRequest.requestHeaders,
                requestBody: networkRequest.requestBody,
                status: nil,
                responseHeaders: nil,
                responseBody: nil,
                startTime: networkRequest.startTime,
                endTime: networkRequest.endTime,
                durationMs: networkRequest.durationMs,
                error: error.localizedDescription
            )
        } else if let response = task.response as? HTTPURLResponse {
            networkRequest = DiagnosticsNetworkRequest(
                id: requestId,
                url: networkRequest.url,
                method: networkRequest.method,
                requestHeaders: networkRequest.requestHeaders,
                requestBody: networkRequest.requestBody,
                status: response.statusCode,
                responseHeaders: response.allHeaderFields as? [String: String],
                responseBody: nil, // Don't capture response body (too large)
                startTime: networkRequest.startTime,
                endTime: networkRequest.endTime,
                durationMs: networkRequest.durationMs,
                error: nil
            )
        }
        
        NetworkInterceptor.onRequest?(networkRequest)
        
        if let error = error {
            client?.urlProtocol(self, didFailWithError: error)
        } else {
            client?.urlProtocolDidFinishLoading(self)
        }
    }
    
    private static func sanitizeHeader(_ value: String, key: String) -> String {
        let sensitivePatterns = ["authorization", "cookie", "token", "api-key"]
        let lowerKey = key.lowercased()
        
        for pattern in sensitivePatterns {
            if lowerKey.contains(pattern) {
                return "[REDACTED]"
            }
        }
        return value
    }
}
