//
//  DDAlamofire.swift
//  DDNetworkingOfAlamofireKit_Private
//
//  Created by 中道 on 2023/7/24.
//

import Foundation
import Alamofire

public protocol DDAlamofireDelegate : AnyObject {
    func errorCodeHandler<T:Decodable>(response:AFDataResponse<T>) -> AFDataResponse<T>
    func networkErrorHandler<T:Decodable>(response:AFDataResponse<T>) -> AFDataResponse<T>
    func completionHandler<T:Decodable>(response:AFDataResponse<T>) -> AFDataResponse<T>
}
public extension DDAlamofireDelegate {
    func errorCodeHandler<T:Decodable>(response:AFDataResponse<T>) -> AFDataResponse<T> { return response }
    func networkErrorHandler<T:Decodable>(response:AFDataResponse<T>) -> AFDataResponse<T> { return response }
    func completionHandler<T:Decodable>(response:AFDataResponse<T>) -> AFDataResponse<T> { return response }
}

open class DDAlamofire : NSObject {

    // MARK: instance
    public static let `default` = DDAlamofire()
    public var delegate : DDAlamofireDelegate?

    // MARK: configuration
    public func request<T: Decodable,P: Encodable>(urlString:String,method:HTTPMethod,parameters:P? = nil,encoding:ParameterEncoder = URLEncodedFormParameterEncoder.default,headers:HTTPHeaders? = nil,responseType:T.Type = T.self,completionHandler: @escaping ((AFDataResponse<T>) -> Void)) {
        let _ = AF.request(urlString: urlString, method: method, parameters: parameters, encoding: encoding, headers: headers, requestModifier: {$0.timeoutInterval = 15}, responseType: responseType) {[weak self] response in
            if let response = self?.dealWithResponse(response: response) {
                completionHandler(response)
            }
        }
    }
    
    public func request<T: Decodable>(urlString:String,method:HTTPMethod,parameters:[String:Any]? = nil,encoding:ParameterEncoding = URLEncoding.default,headers:HTTPHeaders? = nil,responseType:T.Type = T.self,completionHandler: @escaping ((AFDataResponse<T>) -> Void)) {
        let _ = AF.request(urlString: urlString, method: method, parameters: parameters, encoding: encoding, headers: headers, requestModifier: {$0.timeoutInterval = 15}, responseType: responseType) {[weak self] response in
            if let response = self?.dealWithResponse(response: response) {
                completionHandler(response)
            }
        }
    }
    
    public func upload<T: Decodable>(urlString:String,method:HTTPMethod,headers:HTTPHeaders? = nil,responseType:T.Type = T.self,multipartFormData: @escaping (MultipartFormData) -> Void,uploadProgress: @escaping (Progress) -> Void,completionHandler: @escaping ((AFDataResponse<T>) -> Void)) {
        let _ = AF.upload(multipartFormData: { muiltipart in
            multipartFormData(muiltipart)
        }, urlString: urlString,method: method,headers: headers,requestModifier: {$0.timeoutInterval = 15},uploadProgress: { progress in
            uploadProgress(progress)
        },responseType: responseType) {[weak self] response in
            if let response = self?.dealWithResponse(response: response) {
                completionHandler(response)
            }
        }
    }
    
    private func dealWithResponse<T:Decodable>(response:AFDataResponse<T>) -> AFDataResponse<T> {
        var returnResponse : AFDataResponse<T>

        if let delegate {
            if response.response?.statusCode == nil {
                returnResponse = delegate.networkErrorHandler(response: response)
            }else if response.response?.statusCode != 200 {
                returnResponse = delegate.errorCodeHandler(response: response)
            }else{
                returnResponse = delegate.completionHandler(response: response)
            }
        }else{
            returnResponse = response
        }
      
        return returnResponse
    }
}

// MARK: AF Extension
extension Session {
    // 参数遵循Encodable
    public func request<T: Decodable,P: Encodable>(urlString:String,method:HTTPMethod,parameters:P? = nil,encoding:ParameterEncoder = URLEncodedFormParameterEncoder.default,headers:HTTPHeaders? = nil,interceptor:RequestInterceptor? = nil,requestModifier:Session.RequestModifier? = nil,responseType:T.Type = T.self,completionHandler: @escaping ((AFDataResponse<T>) -> Void)) -> DataRequest {
        return request(urlString,method: method,parameters: parameters,encoder: encoding,headers: headers,interceptor: interceptor,requestModifier: requestModifier).responseDecodable(of:responseType,queue: .global()) { response in
            completionHandler(response)
        }
    }
    // 参数为字典
    public func request<T: Decodable>(urlString:String,method:HTTPMethod,parameters:Parameters? = nil,encoding:ParameterEncoding = URLEncoding.default,headers:HTTPHeaders? = nil,interceptor:RequestInterceptor? = nil,requestModifier:Session.RequestModifier? = nil,responseType:T.Type = T.self,completionHandler: @escaping ((AFDataResponse<T>) -> Void)) -> DataRequest {
        return request(urlString,method: method,parameters: parameters,encoding: encoding,headers:headers,interceptor:interceptor,requestModifier:requestModifier).responseDecodable(of: responseType,queue: .global()) { response in
            completionHandler(response)
        }
                
    }
    
    public func upload<T: Decodable>(multipartFormData:@escaping (MultipartFormData) -> Void,urlString:String,usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,method: HTTPMethod = .post,headers: HTTPHeaders? = nil,interceptor: RequestInterceptor? = nil,fileManager: FileManager = .default,requestModifier: RequestModifier? = nil,uploadProgress: @escaping (Progress) -> Void,responseType:T.Type = T.self,completionHandler: @escaping ((AFDataResponse<T>) -> Void)) -> DataRequest {
        return upload(multipartFormData: multipartFormData, to: urlString,usingThreshold: encodingMemoryThreshold,method: method,headers: headers,interceptor: interceptor,fileManager: fileManager,requestModifier: requestModifier).uploadProgress(queue: .global(),closure: uploadProgress).responseDecodable(of: responseType,queue: .global()) { response in
            completionHandler(response)
        }
    }
}
