//
//  YHAIRequestManager.swift
//  galaxy
//
//  Created by Dufet on 2024/11/25.
//  Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//

import UIKit
import Alamofire
import SmartCodable

class YHAIRequestManager: NSObject {

    static let sessionKey = "YINHE_SESSION_KEY"
    
    static let subrobotConversationConfigKey = "subrobot_conversation_config_key"
    
    var sessionId: String = ""
    var request: DataStreamRequest?
    
    let prefix_id = "id:"
    let prefix_event = "event:"
    let prefix_data = "data:"
    let viewModel = YHAIViewModel()
        
    var uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description
    var chatId = ""
    
    var disableHandleMessage: Bool = false

    
    func getCommonHeaders() -> HTTPHeaders {
        
        var requestHeader = HTTPHeaders()
        requestHeader.add(name: "Accept", value: "text/event-stream")
        requestHeader.add(name:"appid",value:"1")
        let dateStr = String(Date().timeIntervalSince1970)
        requestHeader.add(name:"timestamp",value:dateStr)
        
        requestHeader.add(name:"app_platform",value:"iOS")
        requestHeader.add(name:"app_os",value:"iOS")
        let version = UIDevice.appVersion()
        requestHeader.add(name:"app_version",value:version)
        requestHeader.add(name:"app_channel",value:"appStore")
        
        requestHeader.add(name:"app_phoneModel",value:UIDevice.iPhoneModelName())
        requestHeader.add(name:"os_version_name",value:UIDevice.iPhoneVersion())
        
        requestHeader.add(name:"pass",value:"")
        
        let appkey = "958364f87222c200a72414f492bf0e26"
        let signOrgiString = "appid=" + "1" + "&" + "timestamp=" + dateStr + "&" + "appkey=" + appkey
        let sign = signOrgiString.md5()
        print("sign = \(sign)")
        
        requestHeader.add(name:"sign",value:sign)
        requestHeader.add(name: "token", value: YHLoginManager.shared.userModel?.token ?? "-")
        if !YHLoginManager.shared.deviceTokenModel.registerId.isEmpty {
            requestHeader.add(name: "device-id", value: YHLoginManager.shared.deviceTokenModel.registerId)
        }
        return requestHeader
    }
    
    func cancelCurrentRequest() {
        self.request?.responseStreamString {
            stream in
        }
        self.request?.cancel()
        self.request = nil
    }
    
    func requestAI(botId: String, conversationId: String, question: String = "", callback: ((_ msg: YHAIChatMessage?, _ done: Bool) -> Void)?) {

            self.disableHandleMessage = false
        
            let url = YHBaseUrlManager.shared.curURL() + YHAllApiName.AIChat.agentChat
            self.uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description

            // body 请求体参数
            let parameters = ["botId" : botId,
                              "conversationId" : conversationId,
                              "question" : question] as! [String: Any]

            print("AI QUESTION PARAM: \(parameters)")
            let headers = self.getCommonHeaders()

            // 发送 POST 请求
            request = AF.streamRequest(url,
                                       method: .post,
                                       headers: headers,
                                       automaticallyCancelOnStreamError: false,
                                       requestModifier: { request in
                                             if let httpBodyStream = self.dictionaryToHttpBodyStream(parameters) {
                                                 request.httpBodyStream = httpBodyStream
                                             }
                                         }).responseStreamString {
                                             
                                    [weak self] stream in
                                    guard let self = self else { return }
                                             
                                     if self.disableHandleMessage {
                                         return
                                     }

                                    switch stream.event {
                                    case let .stream(result):
                                        switch result {
                                        case let .success(string):
                                            print(string)
                                            
                                            self.handle(dataString: string) {
                                                response, done in
                                                callback?(response, done)
                                            }
                                        case let .failure(error):
                                            print("\(error)")
                                            // 一段话结束需要重新生成uuid 来
//                                            self.uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description
//                                            callback?(nil, true)
                                        }
                                    case let .complete(completion):
                     
                                        print("COMPLETE")
                                        // 一段话结束需要重新生成uuid 来
//                                        self.uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description
//                                        callback?(nil, true)
                                        
                                        if let af_error = completion.error {
                                            
                                            if let error = af_error.underlyingError {
                                                print("\(error)")
                                            } else {
                                                print("&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
                                            }
                                            
                                        } else if let res = completion.response {
                                            print("&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
                                            print("\(res)")

                                        } else {
                                            print("response done")
                                        }
                                    }
                                }
    }
    
    func stopChat(chatId: String, conversationId: String, callBackBlock:@escaping (_ success: Bool,_ error:YHErrorModel?)->()) {
        
        let url = YHBaseUrlManager.shared.curURL() + YHAllApiName.AIChat.cancelAIChat
        let param = ["chatId" : chatId,
                     "conversationId" : conversationId] as! [String: Any]
        
        let _ = YHNetRequest.postRequest(url: url, params: param) { [weak self] json, code in
            //1. json字符串 转 对象
            guard let self = self else { return }
            printLog("model 是 ==> \(json)")
            
            if json.code == 200 {
                callBackBlock(true,nil)
            } else {
                let err = YHErrorModel(errorCode: Int32(json.code), errorMsg: json.msg.isEmpty ? "" : json.msg)
                callBackBlock(false,err)
            }
        } failBlock: { err in
            callBackBlock(false,err)
        }
    }
    
    func dictionaryToHttpBodyStream(_ dic: [String: Any]) -> InputStream? {
        do {
            // 将字典序列化为 JSON 数据
            let jsonData = try JSONSerialization.data(withJSONObject: dic, options: [])
            // 创建一个 InputStream
            let stream = InputStream(data: jsonData)
            return stream
            
        } catch {
            print("Error serializing dictionary to JSON: \(error)")
            return nil
        }
    }
    
    // 处理data字符串
    func handle(dataString: String, completion:((_ : YHAIChatMessage?, _ done: Bool) ->())?) {
        
        let arr = dataString.components(separatedBy: "\n\n")
        if arr.count <= 0 {
            return
        }
        
        for text in arr {
            if text.isEmpty {
                continue
            }
            let lines = text.components(separatedBy: "\n")
            if lines.count > 0 {
                let receiveMessage = YHAIChatMessage()
                receiveMessage.messageId = uuid
                for line in lines {
                    if line.starts(with: prefix_id) {
                        if let idRange = line.range(of: prefix_id) {
                            let id = String(line[idRange.upperBound...])
                            receiveMessage.id = id
                        }
                        
                    } else if line.starts(with: prefix_event) {
                        if let eventRange = line.range(of: prefix_event) {
                            let eventString = String(line[eventRange.upperBound...])
                            receiveMessage.event = eventString
                        }
                        
                    } else if line.starts(with: prefix_data) {
                        if let dataRange = line.range(of: prefix_data) {
                            let jsonString = String(line[dataRange.upperBound...])
                            receiveMessage.data = jsonString
                            do {
                                if let jsonData = jsonString.data(using: .utf8) {
                                    let jsonDict = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any]
                                    let dic = (jsonDict ?? [:])
                                    receiveMessage.dataDict = dic
                                    if let body = YHAIMessageBody.deserialize(from: dic) {
                                        receiveMessage.body = body
                                    }
                                }
                                
                            } catch {
                                
                            }
                        }
                    }
                    if receiveMessage.body.isStart() {
                        chatId = receiveMessage.body.chatId
                    }
                }
                
                print("MESSAGE_RECEIVE:\n \(receiveMessage)")
                
                var sessionDone = receiveMessage.body.isDone()
                if sessionDone {
                    print("SESSION DONE")
                }
                if receiveMessage.isMessageCompleted() {
                    // 一段话结束需要重新生成uuid 来
                    self.uuid = UUID().uuidString + NSDate().timeIntervalSince1970.description
                }
                
                if receiveMessage.isUserfulMessage() {
                    if receiveMessage.body.isDone() {
                        completion?(nil, sessionDone)
                    } else {
                        completion?(receiveMessage, sessionDone)
                    }
                }
            }
        } // arr 结束
    }
}

extension YHAIRequestManager {
    
    func getMainChatConversationId(completion:((String)->())?) {
        
        let sessionId = getLocalGlobalConverastionId()
        if !sessionId.isEmpty {
            completion?(sessionId)
            return
        }
        self.viewModel.requestConversationId { sessionId in
            self.saveGlobalConverastionId(sessionId)
            completion?(sessionId)
        }
    }
    
    func saveGlobalConverastionId(_ conversationId: String) {
        let userId = YHLoginManager.shared.userModel?.id ?? ""
        let key = Self.sessionKey + userId
        UserDefaults.standard.set(conversationId, forKey: key)
        UserDefaults.standard.synchronize()
    }

    
    func getLocalGlobalConverastionId() -> String {
        let userId = YHLoginManager.shared.userModel?.id ?? ""
        let key = Self.sessionKey + userId
        if let sessionId = UserDefaults.standard.value(forKey: key) as? String, !sessionId.isEmpty {
            return sessionId
        }
        return ""
    }
    
    func clearGlobalConverastionId() {
        let userId = YHLoginManager.shared.userModel?.id ?? ""
        let key = Self.sessionKey + userId
        UserDefaults.standard.set(nil, forKey: key)
        UserDefaults.standard.synchronize()
    }
    
    func getSubRobotChatConversationId(listItemId: String, completion:((String)->())?) {
        
        let localConversationId = getLobalSubRobotConversationId(listItemId: listItemId)
        if !localConversationId.isEmpty {
            completion?(localConversationId)
            return
        }
        self.viewModel.requestConversationId { sessionId in
            self.saveLobalSubRobotConversationId(sessionId, listItemId: listItemId)
            completion?(sessionId)
        }
    }
    
    func getLobalSubRobotConversationId(listItemId: String) -> String {
        let userId = YHLoginManager.shared.userModel?.id ?? ""
        let key = Self.subrobotConversationConfigKey + userId
        if let dict = UserDefaults.standard.dictionary(forKey: key) {
            if let conversationId = dict["\(listItemId)"] as? String, !conversationId.isEmpty {
                return conversationId
            }
        }
        return ""
    }
    
    func saveLobalSubRobotConversationId(_ converId: String, listItemId: String) {
        let userId = YHLoginManager.shared.userModel?.id ?? ""
        let key = Self.subrobotConversationConfigKey + userId
        var dict:[String : Any] = [:]
        if let config = UserDefaults.standard.dictionary(forKey: key) {
            dict = config
        }
        dict["\(listItemId)"] = converId
        UserDefaults.standard.set(dict, forKey: key)
        UserDefaults.standard.synchronize()
    }
    
    func clearLobalSubRobotConversationIdForListItemId(_ listItemId: String) {
        saveLobalSubRobotConversationId("", listItemId: listItemId)
    }
}
