import Foundation
import GenAPI

public extension AnyJSON {
    var boolValue: Bool? {
        guard case .bool(let bool) = self else { return nil }
        return bool
    }

    var doubleValue: Double? {
        guard case .number(let double) = self else { return nil }
        return double
    }

    var intValue: Int? {
        doubleValue.map(Int.init)
    }

    var stringValue: String? {
        guard case .string(let string) = self else { return nil }
        return string
    }

    var underlying: Any {
        switch self {
        case .string(let string): return string
        case .number(let number): return number
        case .object(let dict): return dict.mapValues { $0.underlying }
        case .array(let array): return array.map { $0.underlying }
        case .bool(let bool): return bool
        case .null: return NSNull()
        }
    }

    // Create AnyJSON from any Codable type
    static func from<T: Encodable>(_ value: T) throws -> AnyJSON {
        // First encode the Codable value to Data
        let encoder = JSONEncoder()
        encoder.keyEncodingStrategy = .convertToSnakeCase // Ensure snake_case for consistency with API
        let data = try encoder.encode(value)

        // Then decode that data as AnyJSON
        return try JSONDecoder().decode(AnyJSON.self, from: data)
    }

    // Create any Codable type from AnyJSON
    func to<T: Decodable>(_ type: T.Type) throws -> T {
        // First convert AnyJSON to a dictionary or array
        let jsonObject = self.underlying

        // Convert to Data
        let data = try JSONSerialization.data(withJSONObject: jsonObject)

        // Then decode that data as AnyJSON
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase // Ensure snake_case for consistency with API
        return try decoder.decode(type, from: data)
    }
}
