//
//  IMManager.swift

//
//  Created by Leon on 2025/8/18.
//

import NIMSDK
import Combine
import UserNotifications

class IMManager: NSObject {
    public static let shared = IMManager()
    
    var retryCount = 0
    // appkey信息
    var imInfo: IMConfigInfo?
    
    // 给oc用的
    var accountId: String {
        imInfo?.accountId ?? ""
    }
    
    // session Cache
    var cacheSessions = [String]()
    
    // Config是否需要发送通知
    var notNeedSendNotification = false
    
    // UnreadCount 未读消息
    var totalUnreadCount: Int {
        return chatTabAllUnreadCount
    }
    
    /// 🔥 chat tab 的未读总数
    @Published var chatTabAllUnreadCount: Int = 0
    
    /// 🔥notice center 入口的未读数
    @Published var noticeUnreadCount: Int = 0
    @Published var noticeStat: MessageStat?
    
    /// 🔥IM 消息未读数
    @Published var sessionUnreadCount: Int = 0
    
    private var cancellables = Set<AnyCancellable>()
    
    override init() {
        super.init()
        setupDefaultConfig()
        setupEvent()
    }
    
    
    func setupEvent() {
        NotificationCenter.default.addObserver(self, selector: #selector(notiLoginSuccess), name: AppNotificationName.userLoginSuccess.notificationName, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(notiLogout), name: AppNotificationName.userLogout.notificationName, object: nil)
        
        //
//        UserCore.shared.isLogin()
        
        Publishers.CombineLatest($noticeUnreadCount, $sessionUnreadCount)
            .map { $0 + $1 }
            .assign(to: \.chatTabAllUnreadCount, on: self)
            .store(in: &cancellables)
        
        $chatTabAllUnreadCount.sink { count in
            UIApplication.shared.applicationIconBadgeNumber = count
        }.store(in: &cancellables)
    }
    
    // sdk配置基础
    func setupDefaultConfig() {
        let config = NIMSDKConfig.shared()
        
        // config.delegate = self
        // 同步多端未读数
        config.shouldSyncUnreadCount = true
        // 链接失败重试次数
        config.maxAutoLoginRetryTimes = 10
        // 本地log存储天数
        config.maximumLogDays = 30
        // 是否将群通知计入未读数
        config.shouldCountTeamNotification = true
        // 是否支持动图缩略
        config.animatedImageThumbnailEnabled = false
        // 是否在收到消息后自动下载附件
        config.fetchAttachmentAutomaticallyAfterReceiving = false
        // 是否在收到聊天室消息后下载附件
        config.fetchAttachmentAutomaticallyAfterReceivingInChatroom = true
        // 是否开启异步获取最近会话
        config.asyncLoadRecentSessionEnabled = true
        // 禁止后台重连，退到后台即断开
        config.reconnectInBackgroundStateDisabled = true
        // 置顶会话同步开关。如果不使用置顶功能建议关闭（默认），有利于节省流量
        config.shouldSyncStickTopSessionInfos = false
    }
    
    /// 🔥启动初始化SDK，主要入口
    public func setupNIM() {

        NIMSDK.shared().v2LoginService.add(self)
        NIMSDK.shared().v2ConversationService.add(self)
        NIMSDK.shared().v2SubscriptionService.add(self)
        NIMSDK.shared().v2MessageService.add(self)
        
        // 初始化SDK
        v2InitailSDK()
        
        refreshIMServerInfoConfig()
        //setupNIMAppKey()
    }
    
    func v2InitailSDK(){
//        guard UserCore.shared.isLogin() else {
//            return
//        }
        
        let appkey = "2d6abc076f434fc52320c7118de5fead"
        
        var option = NIMSDKOption.init(appKey: appkey)
#if DEBUG
        option.apnsCername = "developerpush"
#else
        option.apnsCername = "distributionpush"
#endif
        let v2Option = V2NIMSDKOption()
        v2Option.enableV2CloudConversation = true
        
        NIMSDK.shared().register(withOptionV2: option, v2Option: v2Option)
        
        if NIMSDK.shared().loginManager.isLogined(){
            dlog("💬❌ NIMSDK 已登录")
        }
        
        // v2AutoLogin()
    }
    
    func v2AutoLogin(){
        if imInfo == nil {
            // 从本地取
            if let info = AppCache.fetchCache(key: CacheKey.ImAppkeyInfo.rawValue, type: IMConfigInfo.self) {
                imInfo = info
            } else {
                return
            }
        }
        
        guard UserCore.shared.isLogin() else { return }
        guard let info = imInfo else { return }
        guard let account = info.accountId else { return }
        guard let imToken = info.token else { return }
        let option = V2NIMLoginOption()
        option.retryCount = 3
        NIMSDK.shared().v2LoginService.login(account, token: imToken, option: option) {[weak self] in
            // dlog("☁️Log Success")
            self?.regetConversationAllUnreadCount()
        }
    }
    
    func logoutIM(){
        NIMSDK.shared().v2LoginService.logout {
            dlog("☁️Log out")
        } failure: { error in
            dlog("☁️Log error: \(error)")
        }

    }
    
    /// 清理当前账号的IM登录信息
    private func clearLogData() {
        resetCount()
        UserCore.shared.logout()
        NotificationCenter.post(name: .presentSignInVc, object: nil, userInfo: nil)
    }
    
    func handleReceiveCreate(recentSession: V2NIMConversation) {
        guard let message = recentSession.lastMessage else { return }
        dealNotice(message: message)
    }
    
    /// 全局收到消息，针对性处理一些消息
    func handleReveiceUpdate(recentSession: V2NIMConversation) {
        guard let message = recentSession.lastMessage else { return }
        if let remoteExt = message.serverExtension{
//            if let type = remoteExt["type"] as? String{
//                if type == MessageTypeStringCustom || type == MessageTypeStringNormal, let session = recentSession.session{
//                    // 打电话的消息，交给打电话处理
//                    dealPhoneCallMessage(message: message, session: session)
//                }
//            }
        }else if message.messageType == .MESSAGE_TYPE_CUSTOM {
            // 自定义消息，暂不处理
        }
        
        if message.messageType == .MESSAGE_TYPE_CUSTOM{
            
        }else{
            dealNotice(message: message)
        }
    }
    
    func dealNotice(message: V2NIMLastMessage) {
        // NIMMessage
        guard UIApplication.shared.applicationState == .active else {
            return
        }
        let generator = UIImpactFeedbackGenerator(style: .medium)
        generator.impactOccurred()

    }
}

// loadData
extension IMManager {
    /// 刷新app 信息
    func refreshIMServerInfoConfig() {
        guard UserCore.shared.isLogin() else {
            return
        }
        guard retryCount <= 5 else {
            // 重试最多五次
            return
        }
        
        IMProvider.request(.getIMAccount, modelType: IMConfigInfo.self) {[weak self] result in
            switch result {
            case let .success(model):
                if model != nil {
                    self?.imInfo = model
                    AppCache.cache(key: CacheKey.ImAppkeyInfo.rawValue, value: model)
                    //self?.setupNIMAppKey()
                    self?.v2AutoLogin() //
                    self?.retryCount = 0
                }
                if String.realEmpty(str: model?.accountId) {
                    // 控制重试时间
                    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                        self?.refreshIMServerInfoConfig()
                        self?.retryCount += 1
                    }
                }
            case let .failure(error):
                dlog(error)
                // 控制重试时间
                DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                    self?.refreshIMServerInfoConfig()
                    self?.retryCount += 1
                }
            }
        }
    }
    
    public func retryRefreshConfig() {
        if NIMSDK.shared().loginManager.isLogined() {
            return
        }
        // 重试登录
        retryCount = 0
        refreshIMServerInfoConfig()
    }
    
}

// MARK: 🔴Unread Count 未读数和红点处理

extension IMManager {
    
    public func regetAllUnreadCount(){
        regetNoticeUnread()
        regetConversationAllUnreadCount()
    }
    
    /// 请求业务系统上的未读数
    func regetNoticeUnread(completion:((Bool, MessageStat?)-> Void)? = nil){
        guard UserCore.shared.isLogin() else{
            completion?(false, nil)
            return
        }
        IMProvider.request(.messageStat, modelType: MessageStat.self) {[weak self] result in
            switch result {
            case .success(let model):
                self?.noticeStat = model
                self?.noticeUnreadCount = model?.unRead ?? 0
                completion?(true, model)
            case .failure:
                break
            }
        }
    }

    
    public func regetConversationAllUnreadCount(){
        // 获取未读数
        sessionUnreadCount = NIMSDK.shared().v2ConversationService.getTotalUnreadCount()
        dlog("🚩IMManager reget unread count:\(sessionUnreadCount)")
    }
    
    func registerNIMCount(){
        let filter = V2NIMConversationFilter()
        filter.conversationTypes = [1]//V2NIMConversationType.CONVERSATION_TYPE_P2P
        filter.ignoreMuted = true
        NIMSDK.shared().v2ConversationService.subscribeUnreadCount(by: filter)
        // Result can see in onUnreadCountChangedByFilter
    }
    
    /// 🔥conversationIds
    func clearUnreadCountBy(ids:[String]){
        guard ids.count > 0 else{ return }
        NIMSDK.shared().v2ConversationService.clearUnreadCount(byIds: ids) {[weak self] resuls in
            let getUnreadcount = NIMSDK.shared().v2ConversationService.getTotalUnreadCount()
            // dlog("💬getTotalUnreadCount: \(getUnreadcount)")
            self?.sessionUnreadCount = getUnreadcount
        }
    }
    
    func clearAllUnread(){
        NIMSDK.shared().v2ConversationService.clearTotalUnreadCount {
            dlog("☁️Clear all unread message ok✅")
        }
    }
    
    // 重置未读数
    func resetCount() {
        notNeedSendNotification = true
        sessionUnreadCount = 0
        noticeUnreadCount = 0
        notNeedSendNotification = false
        
    }

}

extension IMManager: V2NIMLoginListener{
    func onLoginStatus(_ status: V2NIMLoginStatus) {
        dlog("☁️login status:\(status)")
        if status == .LOGIN_STATUS_LOGINED{
            // 登录成功
            dlog("☁️login success")
            // 注册未读数
            registerNIMCount()
            
            regetConversationAllUnreadCount()
            
            regetNoticeUnread()
        }
    }
    
    
    
    func onKickedOffline(_ detail: V2NIMKickedOfflineDetail) {
        // 判断是否登录
        guard UserCore.shared.isLogin() else {
            return
        }
        
        let reason = "Your account has signed in through another device"

        
        let alert = Alert(title: "Session Interrupted", text: reason)
        let action1 = AlertAction(title: "Got it", actionStyle: .confirm) {[weak self] in
            self?.clearLogData()
        }
        alert.addAction(action1)
        alert.show()
    }
    
    func onLoginFailed(_ error: V2NIMError) {
        dlog("☁️onAutoLoginFailed__ \(error.description)")
        if error.code == 417 {
            guard let  _ = imInfo?.accountId, let _ = imInfo?.token else { return }
            v2AutoLogin()
        }
    }
}

// MARK: NIMConversationManagerDelegate

extension IMManager: V2NIMConversationListener{
    func onSyncStarted() {
        dlog("☁️onSyncStarted")
    }
    
    func onSyncFinished() {
        dlog("☁️onSyncFinished")
    }
    
    func onSyncFailed(_ error: V2NIMError) {
        dlog("☁️onSyncFailed:\(error)")
    }
    
    func onConversationCreated(_ conversation: V2NIMConversation) {
        handleReveiceUpdate(recentSession: conversation)
    }
    
    func onConversationChanged(_ conversations: [V2NIMConversation]) {
        for per in conversations{
            handleReveiceUpdate(recentSession: per)
        }
    }
    
    func onConversationDeleted(_ conversationIds: [String]) {
        dlog("💬🗑️onConversationDeleted: \(conversationIds)")
    }
    
    func onTotalUnreadCountChanged(_ unreadCount: Int) {
        dlog("💬onTotalUnreadCountChanged : \(unreadCount)")
        sessionUnreadCount = unreadCount
    }
    
    // 账号多端登录会话已读时间戳标记通知回调
    func onConversationReadTimeUpdated(_ conversationId: String, readTime: TimeInterval) {
        
    }
    
    func onUnreadCountChanged(by filter: V2NIMConversationFilter, unreadCount: Int) {
        // dlog("☁️unreadCount:\(unreadCount)")
    }
}

extension IMManager  : V2NIMSubscribeListener{
    /// 用户状态变化
    func onUserStatusChanged(_ data: [V2NIMUserStatus]) {
        // none
        dlog("☁️onUserStatusChanged：\(data)")
    }
}

extension IMManager : V2NIMMessageListener{
    func onReceive(_ messages: [V2NIMMessage]) {
        // ...
        regetConversationAllUnreadCount()
        
    }
}

// MARK: Notification
extension IMManager {
    @objc func notiLoginSuccess() {
        retryCount = 0
        refreshIMServerInfoConfig()
        
        
        UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert]) { granted, error in
            print("Notification granted: \(granted), error: \(String(describing: error))")
        }
    }
    
    @objc func notiLogout() {
        imInfo = nil
        resetCount()
        removeAllCache()
        NIMSDK.shared().v2LoginService.logout { [weak self] in
            self?.resetCount()
        }
    }
}

// public cache
extension IMManager {
    public func addCache(sessionID: String) {
        if !cacheSessions.contains(sessionID) {
            cacheSessions.append(sessionID)
        }
    }
    
    public func deleteCache(sessionID: String) {
        if cacheSessions.contains(sessionID) {
            cacheSessions.removeObj(sessionID)
        }
    }
    
    func findCache(sessionID: String) -> Bool{
        return cacheSessions.contains(sessionID)
    }
    
    func removeAllCache() {
        cacheSessions.removeAll()
    }
}

// 消息处理
extension IMManager {
    
    /// 发送消息,  注意这里传云信的account ID，不是用户userID
    static func sendMessage(msgText: String, accID:String) {
        
        if String.realEmpty(str: msgText.trimmed) {
            // 为空，不做操作
            return
        }
        // 创建消息
        let message = IMMessageMaker.msgWithText(msgText)
        // 判断消息是否可以发送
        let canSend = IMManager.dealWillSendMessage(message: message)
        if canSend {
            // 创建会话
//            let session = NIMSession(accID, type: .P2P)
//            NIMSDK.shared().chatManager.send(message, to: session) { error in
//                // 消息发送回调
//                #warning("test action")
//            }
        } else {
             // 这里需不需要处理成本地消息？
        }
    }
    
    // 处理是否能发送消息
    static public func dealWillSendMessage(message: V2NIMMessage) -> Bool {
//        var dict = [String:String]()

//        if message.messageType == .text {
//            // 文本消息，检查敏感词
//            let word = GameDataManager.shared.matchKeywordWith(sourceStr: message.text?.lowercased() ?? "")
//            if word.count > 0 {
//                dict["keyword"] = word
//                dict["type"] = "NOTICE_KEYWORD"
//                message.remoteExt = dict
//                return false
//            }
//        }
        
        return true
    }
}
