//
//  APIProvider.swift
//  WoolniOriginalSwift
//
//  Created by lyu dong on 2025/7/2.
//  Copyright © 2025 lydsnm. All rights reserved.
//

import Foundation
import Moya
import UIKit

let myEndpointClosure = { (target: TargetType) -> Endpoint in
    let url = target.baseURL.absoluteString + target.path
    var task = target.task

    var endpoint = Endpoint(
        url: url,
        sampleResponseClosure: { .networkResponse(200, target.sampleData) },
        method: target.method,
        task: task,
        httpHeaderFields: target.headers
    )
    return endpoint
}

let myRequestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
    do {
        var request = try endpoint.urlRequest()
        request.timeoutInterval = 30
        
        let token = UserCore.shared.token
        if !token.isEmpty {
            let body = request.httpBody ?? Data()
            let str = String(data:body, encoding: .utf8)
            if APIConfig.apiLogEnable {
                // dlog("⚠️ request加密前参数：\(str ?? "")")
            }
            
            /*
             // 加密结果
            let key = (token + "AHkt5aUUtO6HZPid").md5().uppercased()
            let aes = try AES(key: key, iv: "HBB4UO5kEmM4169Z")
            let encrypted = try aes.encrypt(str!.bytes)
            let result = encrypted.toBase64()
            if APIConfig.apiLogEnable {
                // dlog("⚠️ request加密结果：\(result)")
            }
            let dic = ["key": result]
             
            let httpBody = try JSONSerialization.data(withJSONObject: dic, options: .prettyPrinted)
             request.httpBody = httpBody
             */
            
            
        }
        done(.success(request))
    } catch {
        done(.failure(MoyaError.underlying(error, nil)))
    }
}

let myNetworkPlugin = NetworkActivityPlugin.init { changeType, _ in
    switch changeType {
    case .began: dlog("开始请求网络")
    case .ended: dlog("结束请求网络")
    }
}

public enum ServiceErrorEnum: String, Codable {
    case unknow = "-1"
    case unknowEmpty = ""
    case internalError = "00000000"
    case common = "0000"
    
    case sign_usernotexist = "10050002"
    case sign_userLoginclientNotExist = "10050003"
    case sign_userNotAuthorizedClient = "10050004"
    case tokenExpired = "10050005"
    case tokenIllegal = "10050006"
    case accountIsFrozen = "10010002"
    
    /// 用户未登陆
    case sign_usernotLoggedIn = "10050001"
    
    /// 用户账号已被冻结
    case otherAccountFrozen = "10010005"
    /// 账号不存在
    case newAccount = "10010001"
    /// 验证码不正确
    case smscodeIncorrect = "10031001"
    /// 验证码过期
    case smscodeExpired = "10031002"
    /// 用户不存在
    case userExist = "10010004"
    
    case mustNotBeBlank = "00000001"
    
    case imageCheckFailed = "10019999"
    /// 生成图片超时
    case imageGenTimeOut = "8006"
    /// 查看未解锁的AI照片
    case imageBrowseButUnlock = "10010011"
    /// AI用户不存在
    case aiRoleNotExist = "10010012"
    
    /// Coin 余额不足
    case insufficentCoin = "INSUFFICIENT_BALANCE"
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let rawValue = try container.decode(String.self)
        self = ServiceErrorEnum(rawValue: rawValue) ?? .unknow
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .unknow:
            // 编码成一个默认值，例如 "-999"，或直接跳过
            try container.encode("unknown")
        default:
            try container.encode(self.rawValue)
        }
    }
}

// 假设 ResponseData 是一个泛型结构体，用于包装 API 响应
struct ResponseData<T: Codable>: Codable {
    /// OK or ERROR
    let status: String?
    let errorCode: ServiceErrorEnum?
    let errorMsg: String?
    let content: T?
    let traceId : String?
}

class ResponseContentPageData<T: Codable>: Codable{
    var pn: Int?
    var ps: Int?
    var datas: [T]?
    var tc: Int?
    var sortType:String?
    var sortField: String?
}

class RequestPageData:Codable {
    var pn : Int = 1
    var ps : Int = 20
}

public enum ResponseError: Error {
    case serviceError(code: ServiceErrorEnum?, msg: String?)
    case deserializeError
    case networkError
}

//extension ResponseError {
//    enum Code: String, Codable {
//        case tokenExpired
//        case tokenIllegal
//        case accountIsFrozen
//        case sign_usernotexist
//        case sign_usernotLoggedIn
//        case sign_userLoginclientNotExist
//        case sign_userNotAuthorizedClient
//        case newAccount
//        case hcaptchaNeed
//        case common
//    }
//}

extension MoyaProvider {
    @discardableResult
    public func request<T: Codable>(_ target: Target,
                                    progress _: ProgressBlock? = .none,
                                    modelType TTType: T.Type,
                                    autoShowErrMsg: Bool = true,
                                    completion: @escaping (Result<T?, ResponseError>) -> Void) -> Cancellable {
        
        if APIConfig.apiLogEnable {
            // 🗣\(target.method)\n
            var paramsLog = ""
            if case let .requestParameters(parameters, _) = target.task {
                if let jsonData = try? JSONSerialization.data(withJSONObject: parameters, options: [.prettyPrinted]),
                   let jsonString = String(data: jsonData, encoding: .utf8) {
                    paramsLog = "\n\(jsonString)"
                } else {
                    paramsLog = "\(parameters)"
                }
            } else {
                paramsLog = "\(target.task)"
            }
            dlog("headers: \(target.headers ?? ["": ""])\n「🗣️Request」path: ⭐️\(target.path)⭐️\n🗣️⭐️params:\(paramsLog)") //
        }
        
        
        return request(target, completion: { result in
            

            switch result {
            case let .success(response):
                do {
                    // 使用 JSONDecoder 解析 response.data
                    let decoder = JSONDecoder()
                    let data = try decoder.decode(ResponseData<T>.self, from: response.data)

                    // 调试日志：将 JSON 转换为字符串用于日志输出
                    if APIConfig.apiLogEnable {
                        let jsonObject = try JSONSerialization.jsonObject(with: response.data)
                        let jsonData = try JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted)
                        let jsonString = String(data: jsonData, encoding: .utf8) ?? String(data: response.data, encoding: .utf8) ?? ""
                        dlog("👉⭐️\(target.path)⭐️ response:\n\(jsonString)")
                    }

                    let status = data.status
                    let code = data.errorCode
                    let msg = data.errorMsg

                    if (status ?? "") == "OK" {
                        let model = data.content
                        completion(.success(model))
                    } else {
                        var toastMsg = autoShowErrMsg
                        
                        if code == .tokenExpired || code == .tokenIllegal || code == .accountIsFrozen || code == .sign_usernotexist || code == .sign_usernotLoggedIn || code == .sign_userLoginclientNotExist || code == .sign_userNotAuthorizedClient {
                            // ⚠️ 弹出登陆
                            UserCore.shared.logout()
                            
                            if let Vc = UIWindow.getTopViewController(), (Vc is CLLoginMainController || Vc is PersonalInformationFillController) {
                                // do nothing.
                            } else {
//                                AppRouter.goBackRootController(jumpIndex: .home) {
//                                    NotificationCenter.post(name: .presentSignInVc, object: nil, userInfo: nil)
//                                }
                                NotificationCenter.post(name: .presentSignInVc, object: nil, userInfo: nil)
                            }
                        } else if code == .newAccount {
                            // ⚠️ 不进行Toast的Msg类型
                            toastMsg = false
                        } else if code == .insufficentCoin {
                            // ⚠️钱包余额不足
                            // refresh wallet
                            toastMsg = false
                            
                            var handled = false
                            if let cow = target as? AICowAPI{
                                switch cow{
                                case .voiceCallOperate, .voiceAsr2, .voiceTts:
                                    IMAIViewModel.shared.showChatModelInsufficentCoinSheet()
                                    handled = true
                                default:
                                    break
                                }
                            }
                            if handled == false{
                                // 弹出充值Sheet
                                CLPurchase.shared.showIAPBuyCoinSheet()
                            }
                        }
                        
                        if toastMsg, let msgUnpack = msg, msgUnpack.count > 0 {
                            UIWindow.getTopDisplayWindow()?.makeToast(msgUnpack)
                        }

                        dlog("⛔️error: code = \(code ?? .common), msg = \(data.errorMsg ?? "业务状态失败")")
                        completion(.failure(.serviceError(code: code, msg: msg)))
                    }

                } catch {
                    dlog("⛔️请求成功，但解析失败: \(error), Response：⛔️\(CodableHelper.jsonString(from: response.data) ?? "x")⛔️")
                    completion(.failure(.deserializeError))
                }

            case let .failure(error):
                dlog("⛔️ \(target.path) 网络连接失败\(error)")
                UIWindow.getTopDisplayWindow()?.makeToast("Internet connection failed")
                completion(.failure(.networkError))
            }
        })
    }
}
