//
//  Common+Ext.swift

//
//  Created by Leon on 2025/7/11.
//

import Foundation

/// 打印
//func dlog<T>(_ message: T, file: StaticString = #file, method: String = #function, line: Int = #line) {
//    #if DEBUG
//        let fileName = (file.description as NSString).lastPathComponent
//        print("🔹\(fileName) \(method)[\(line)]:\n\(message)\n")
//    #endif
//}

func dlog<T>(_ message: T, file: StaticString = #file, method: String = #function, line: Int = #line) {
    #if DEBUG
        let fileName = (file.description as NSString).lastPathComponent
        print("🔹\(fileName) \(method)[\(line)]:\n\(message)\n")
    #endif
}

struct EmptyModel: Codable {}


// MARK: - DecodableValue
enum DecodableValue: Decodable, Encodable {
    case string(String)
    case int(Int)
    case double(Double)
    case bool(Bool)
    case array([DecodableValue])
    case dictionary([String: DecodableValue])
    case null

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()

        if container.decodeNil() {
            self = .null
        } else if let b = try? container.decode(Bool.self) {
            self = .bool(b)
        } else if let i = try? container.decode(Int.self) {
            self = .int(i)
        } else if let d = try? container.decode(Double.self) {
            self = .double(d)
        } else if let s = try? container.decode(String.self) {
            self = .string(s)
        } else if let a = try? container.decode([DecodableValue].self) {
            self = .array(a)
        } else if let dict = try? container.decode([String: DecodableValue].self) {
            self = .dictionary(dict)
        } else {
            throw DecodingError.dataCorruptedError(
                in: container,
                debugDescription: "Unsupported value"
            )
        }
    }
    
    
    // MARK: - Encodable
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()

        switch self {
        case .null:
            try container.encodeNil()
        case .bool(let b):
            try container.encode(b)
        case .int(let i):
            try container.encode(i)
        case .double(let d):
            try container.encode(d)
        case .string(let s):
            try container.encode(s)
        case .array(let a):
            try container.encode(a)
        case .dictionary(let d):
            try container.encode(d)
        }
    }
}

extension Encodable {
    func toNonNilDictionary() -> [String: Any] {
        return Self._toDictionary(value: self)
    }
    
    private static func _toDictionary(value: Any) -> [String: Any] {
        var result: [String: Any] = [:]
        let mirror = Mirror(reflecting: value)
        
        for child in mirror.children {
            guard let key = child.label else { continue }
            
            let rawValue = child.value
            let valueMirror = Mirror(reflecting: rawValue)
            
            // 处理 Optional 类型
            if valueMirror.displayStyle == .optional {
                if let some = valueMirror.children.first?.value {
                    let processedValue = processValue(some)
                    if !isNil(processedValue) {
                        result[key] = processedValue
                    }
                }
                continue
            }
            
            // 处理值
            let processedValue = processValue(rawValue)
            if !isNil(processedValue) {
                result[key] = processedValue
            }
        }
        
        return result
    }
    
    private static func processValue(_ value: Any) -> Any {
        if let rawRepresentable = value as? (any RawRepresentable) {
            return rawRepresentable.rawValue
        }
        
        // 处理特定类型（如 Sex 枚举）
        if let sex = value as? Sex {
            return sex.rawValue
        }
        
        // 处理 Encodable 类型（嵌套结构体或类）
        if let encodableValue = value as? Encodable {
            let mirror = Mirror(reflecting: encodableValue)
            
            // 处理数组或集合
            if mirror.displayStyle == .collection {
                return mirror.children.compactMap { child in
                    let processed = processValue(child.value)
                    return isNil(processed) ? nil : processed
                }
            }
            
            // 处理嵌套结构体或类
            if mirror.displayStyle == .class || mirror.displayStyle == .struct || mirror.displayStyle == .set {
                return _toDictionary(value: encodableValue)
            }
        }
        
        return value
    }
    
    // 辅助函数：检查值是否为 nil
    private static func isNil(_ value: Any) -> Bool {
        let mirror = Mirror(reflecting: value)
        return mirror.displayStyle == .optional && mirror.children.isEmpty
    }
    
//    func toNonNilDictionary() -> [String: Any] {
//        return Self._toDictionary(value: self)
//    }
//    private static func _toDictionary(value: Any) -> [String: Any] {
//        var result: [String: Any] = [:]
//        let mirror = Mirror(reflecting: value)
//        
//        for child in mirror.children {
//            guard let key = child.label else { continue }
//            
//            let rawValue = child.value
//            let valueMirror = Mirror(reflecting: rawValue)
//            
//            // Optional 类型处理
//            if valueMirror.displayStyle == .optional {
//                if let some = valueMirror.children.first?.value {
//                    result[key] = processValue(some)
//                }
//            } else {
//                result[key] = processValue(rawValue)
//            }
//        }
//        
//        return result
//    }
//    
//    private static func processValue(_ value: Any) -> Any {
//        let mirror = Mirror(reflecting: value)
//        
//        // 递归处理 Optional
//        if mirror.displayStyle == .optional {
//            if let some = mirror.children.first?.value {
//                return processValue(some) // 递归处理解包后的值
//            } else {
//                return ""// NSNull() // 或者直接 return "" 视你的需求
//            }
//        }
//        
//        if let sex = value as? Sex {
//            return sex.rawValue
//        }
//        
//        if let encodableValue = value as? Encodable {
//            let mirror = Mirror(reflecting: encodableValue)
//            
//            if mirror.displayStyle == .class || mirror.displayStyle == .struct || mirror.displayStyle == .set {
//                return _toDictionary(value: encodableValue)
//            }
//        }
//        
//        return value
//    }
    
    // MARK: - part 2
    
    /// 将结构体中指定 key 的字段（如果非 nil）导出为字典
    func toPartialDictionary(keys includedKeys: Set<String> = []) -> [String: Any] {
        return Self._toDictionary(value: self, onlyIncludeKeys: includedKeys)
    }

    private static func _toDictionary(value: Any, onlyIncludeKeys: Set<String>? = nil) -> [String: Any] {
        var result: [String: Any] = [:]
        let mirror = Mirror(reflecting: value)

        for child in mirror.children {
            guard let key = child.label else { continue }

            if let allowedKeys = onlyIncludeKeys, !allowedKeys.contains(key) {
                continue
            }

            let rawValue = child.value
            let valueMirror = Mirror(reflecting: rawValue)

            if valueMirror.displayStyle == .optional {
                if let some = valueMirror.children.first?.value {
                    result[key] = processValue(some, onlyIncludeKeys: nil)
                }
            } else {
                result[key] = processValue(rawValue, onlyIncludeKeys: nil)
            }
        }

        return result
    }

    /// 支持将Sex输出为int
    private static func processValue(_ value: Any, onlyIncludeKeys: Set<String>?) -> Any {
        let mirror = Mirror(reflecting: value)

        if mirror.displayStyle == .struct {
            return _toDictionary(value: value, onlyIncludeKeys: onlyIncludeKeys)
        } else if let rawRepresentable = value as? any RawRepresentable {
            return rawRepresentable.rawValue
        } else {
            return value
        }
    }
}


extension Array where Element: Equatable {
    mutating func removeObj(_ object: Element) {
        if let index = firstIndex(of: object) {
            remove(at: index)
        }
    }
}

// MARK: - 通用扩展

extension Optional {
    /// 是否为 nil
    var isNil: Bool { self == nil }

    /// 是否有值
    var isSome: Bool { self != nil }
}

extension Optional where Wrapped == Int {
    /// 是否大于 0
    var isPositive: Bool { (self ?? 0) > 0 }

    /// 是否为负数
    var isNegative: Bool { (self ?? 0) < 0 }

    /// 是否为 nil 或 0
    var isNilOrZero: Bool { self == nil || self == 0 }

    /// 转字符串（nil → ""）
    var stringValue: String { self.map { "\($0)" } ?? "" }
}

extension Optional where Wrapped == String {
    /// 是否为空串或 nil
    var isNilOrEmpty: Bool { self?.isEmpty ?? true }

    /// 去除空格后的安全字符串
    var trimmed: String { self?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" }

    /// 转 Int（失败或 nil 返回 nil）
    var intValue: Int? { self.flatMap { Int($0) } }

    /// 转 Double（失败或 nil 返回 nil）
    var doubleValue: Double? { self.flatMap { Double($0) } }
}

extension Optional where Wrapped == Bool {
    /// 默认 false
    var boolValue: Bool { self ?? false }

    /// 默认 true
    var trueOrNil: Bool { self ?? true }
}

extension Double {
    func formatted(decimal: Int = 2, asPercent: Bool = false, usesGroupingSeparator: Bool = true) -> String {
//        let formatter = NumberFormatter()
//        formatter.minimumFractionDigits = decimal
//        formatter.maximumFractionDigits = decimal
//        formatter.numberStyle = .decimal
//        return formatter.string(from: NSNumber(value: self)) ?? "\(self)"
        
        let value = asPercent ? self * 100 : self
        
        let formatter = NumberFormatter()
        formatter.minimumFractionDigits = decimal
        formatter.maximumFractionDigits = decimal
        formatter.usesGroupingSeparator = usesGroupingSeparator
        formatter.numberStyle = .decimal
        
        let result = formatter.string(from: NSNumber(value: value)) ?? "\(value)"
        return asPercent ? result + "%" : result
    }
}

extension CGFloat {
    func formatted(decimal: Int = 2, asPercent: Bool = false, usesGroupingSeparator: Bool = true) -> String {
        let value = asPercent ? self * 100 : self
        
        let formatter = NumberFormatter()
        formatter.minimumFractionDigits = decimal
        formatter.maximumFractionDigits = decimal
        formatter.usesGroupingSeparator = usesGroupingSeparator
        formatter.numberStyle = .decimal
        
        let result = formatter.string(from: NSNumber(value: value)) ?? "\(value)"
        return asPercent ? result + "%" : result
    }
}

extension Dictionary {
    func merged(with other: Dictionary, preferNew: Bool = true) -> Dictionary {
        return self.merging(other) { old, new in preferNew ? new : old }
    }
}
