//
//  APIResponseDebugger.swift
//  AppClientBaseSwift
//
//  Helper for debugging API response issues
//  Helper để debug các vấn đề API response
//

import Foundation

// MARK: - API Response Debugger
// Debugger cho API Response

/// Helper class for debugging API responses
/// Class helper để debug API responses
struct APIResponseDebugger {
    
    /// Print detailed information about raw JSON data
    /// In thông tin chi tiết về raw JSON data
    /// - Parameters:
    ///   - data: Raw JSON data / Dữ liệu JSON thô
    ///   - expectedType: Expected type name / Tên type mong đợi
    static func debugJSONData(_ data: Data, expectedType: String) {
        #if DEBUG
        print("\n" + String(repeating: "=", count: 60))
        print("🔍 API RESPONSE DEBUG")
        print(String(repeating: "=", count: 60))
        
        // Print raw JSON
        if let jsonString = String(data: data, encoding: .utf8) {
            print("\n📄 Raw JSON Response:")
            print(jsonString.prettyPrintedJSON ?? jsonString)
        }
        
        // Try to parse as generic JSON object
        if let jsonObject = try? JSONSerialization.jsonObject(with: data),
           let jsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted),
           let prettyJSON = String(data: jsonData, encoding: .utf8) {
            
            print("\n🎨 Pretty Printed JSON:")
            print(prettyJSON)
            
            // Analyze structure
            if let dict = jsonObject as? [String: Any] {
                print("\n🔑 Available Keys:")
                for (key, value) in dict {
                    let valueType = type(of: value)
                    print("  - \(key): \(valueType)")
                }
                
                // Check for wrapper format
                let hasSuccess = dict["success"] != nil
                let hasData = dict["data"] != nil
                let hasError = dict["error"] != nil
                
                if hasSuccess || hasData {
                    print("\n📦 Detected Wrapper Format:")
                    print("  - Has 'success': \(hasSuccess)")
                    print("  - Has 'data': \(hasData)")
                    print("  - Has 'error': \(hasError)")
                    
                    if hasData, let dataValue = dict["data"] {
                        print("\n📊 Data Type: \(type(of: dataValue))")
                        if let dataDict = dataValue as? [String: Any] {
                            print("  Data Keys: \(dataDict.keys.joined(separator: ", "))")
                        }
                    }
                } else {
                    print("\n⚠️ No wrapper detected - direct object response")
                }
            } else if let array = jsonObject as? [[String: Any]] {
                print("\n📊 Array Response with \(array.count) items")
                if let firstItem = array.first {
                    print("  First item keys: \(firstItem.keys.joined(separator: ", "))")
                }
            }
        }
        
        print("\n🎯 Expected Type: \(expectedType)")
        print(String(repeating: "=", count: 60) + "\n")
        #endif
    }
    
    /// Compare expected model fields with actual JSON keys
    /// So sánh các field mong đợi của model với key thực tế trong JSON
    /// - Parameters:
    ///   - data: Raw JSON data / Dữ liệu JSON thô
    ///   - expectedKeys: Expected keys / Các key mong đợi
    static func compareFields(data: Data, expectedKeys: [String]) {
        #if DEBUG
        guard let jsonObject = try? JSONSerialization.jsonObject(with: data),
              let dict = jsonObject as? [String: Any] else {
            print("❌ Cannot parse JSON as dictionary")
            return
        }
        
        print("\n🔍 Field Comparison:")
        print("Expected vs Actual\n")
        
        let actualKeys = Set(dict.keys)
        let expectedSet = Set(expectedKeys)
        
        // Missing keys
        let missing = expectedSet.subtracting(actualKeys)
        if !missing.isEmpty {
            print("❌ Missing Keys (in model but not in JSON):")
            missing.forEach { print("  - \($0)") }
        }
        
        // Extra keys
        let extra = actualKeys.subtracting(expectedSet)
        if !extra.isEmpty {
            print("\n➕ Extra Keys (in JSON but not in model):")
            extra.forEach { print("  - \($0)") }
        }
        
        // Matching keys
        let matching = actualKeys.intersection(expectedSet)
        if !matching.isEmpty {
            print("\n✅ Matching Keys:")
            matching.forEach { print("  - \($0)") }
        }
        
        // Suggest CodingKeys mapping
        if !extra.isEmpty || !missing.isEmpty {
            print("\n💡 Suggestion: Add custom CodingKeys mapping:")
            print("enum CodingKeys: String, CodingKey {")
            for key in expectedKeys {
                if missing.contains(key) {
                    // Try to find similar key in actual
                    let snakeCase = key.toSnakeCase()
                    if actualKeys.contains(snakeCase) {
                        print("    case \(key) = \"\(snakeCase)\"")
                    } else {
                        print("    case \(key) // ⚠️ Not found in response")
                    }
                } else {
                    print("    case \(key)")
                }
            }
            print("}")
        }
        #endif
    }
    
    /// Generate Swift model code from JSON data
    /// Tạo code Swift model từ JSON data
    /// - Parameters:
    ///   - data: Raw JSON data / Dữ liệu JSON thô
    ///   - modelName: Name for the model / Tên cho model
    static func generateModelCode(from data: Data, modelName: String = "GeneratedModel") {
        #if DEBUG
        guard let jsonObject = try? JSONSerialization.jsonObject(with: data),
              let dict = jsonObject as? [String: Any] else {
            print("❌ Cannot parse JSON as dictionary")
            return
        }
        
        print("\n🏗️ Generated Model Code:\n")
        print("struct \(modelName): Codable {")
        
        for (key, value) in dict.sorted(by: { $0.key < $1.key }) {
            let camelKey = key.toCamelCase()
            let swiftType = swiftType(for: value)
            let isOptional = value is NSNull
            
            print("    let \(camelKey): \(swiftType)\(isOptional ? "?" : "")")
            
            if key != camelKey {
                print("    // API key: \"\(key)\"")
            }
        }
        
        print("}")
        print("\n")
        #endif
    }
    
    /// Determine Swift type from JSON value
    /// Xác định Swift type từ giá trị JSON
    private static func swiftType(for value: Any) -> String {
        switch value {
        case is String:
            return "String"
        case is Int:
            return "Int"
        case is Double, is Float:
            return "Double"
        case is Bool:
            return "Bool"
        case is [Any]:
            return "[Any]" // Could be more specific
        case is [String: Any]:
            return "[String: Any]" // Could be more specific
        case is NSNull:
            return "String" // Default to String for null values
        default:
            return "Any"
        }
    }
}

// MARK: - String Extensions for Case Conversion
// Extensions String cho chuyển đổi case

extension String {
    /// Convert string to snake_case
    /// Chuyển string sang snake_case
    func toSnakeCase() -> String {
        let pattern = "([a-z0-9])([A-Z])"
        
        let regex = try? NSRegularExpression(pattern: pattern, options: [])
        let range = NSRange(location: 0, length: count)
        let modString = regex?.stringByReplacingMatches(
            in: self,
            options: [],
            range: range,
            withTemplate: "$1_$2"
        )
        
        return (modString ?? self).lowercased()
    }
    
    /// Convert string to camelCase
    /// Chuyển string sang camelCase
    func toCamelCase() -> String {
        let components = self.components(separatedBy: "_")
        guard components.count > 1 else { return self }
        
        let first = components[0].lowercased()
        let rest = components.dropFirst().map { $0.capitalized }.joined()
        
        return first + rest
    }
}

// MARK: - Example Usage
// Ví dụ sử dụng

#if DEBUG
extension APIResponseDebugger {
    /// Example of how to use the debugger
    /// Ví dụ cách sử dụng debugger
    static func exampleUsage() {
        let sampleJSON = """
        {
            "success": true,
            "data": {
                "id": "123",
                "email": "test@example.com",
                "first_name": "John",
                "last_name": "Doe",
                "email_confirmed": true,
                "created_at": "2024-01-01T00:00:00Z"
            }
        }
        """
        
        guard let data = sampleJSON.data(using: .utf8) else { return }
        
        // Debug full response
        debugJSONData(data, expectedType: "APIResponse<User>")
        
        // Compare fields
        let expectedUserFields = [
            "id", "email", "name", "firstName", "lastName",
            "avatarUrl", "phoneNumber", "isEmailVerified",
            "createdAt", "updatedAt", "roles"
        ]
        compareFields(data: data, expectedKeys: expectedUserFields)
        
        // Generate model
        generateModelCode(from: data, modelName: "User")
    }
}
#endif
