//
//  LNRoomManager.swift
//  Gami
//
//  Created by OneeChan on 2026/3/9.
//

import Foundation
import AtomicXCore
import RTCRoomEngine


protocol LNRoomManagerNotify {
    func onUserRoomAbilityChanged()
    func onHallEntranceChanged()
}
extension LNRoomManagerNotify {
    func onUserRoomAbilityChanged() { }
    func onHallEntranceChanged() { }
}


func showTencentError(_ error: ErrorInfo) {
    let items = error.message.components(separatedBy: ",")
    for item in items {
        let parts = item.components(separatedBy: ":")
        if parts.first?.trimmingCharacters(in: .whitespaces) == "error_message" {
            showToast(parts.dropFirst().joined(separator: ":").trimmingCharacters(in: .whitespaces))
            return
        }
    }
    showToast(error.message)
}

class LNRoomManager {
    static let shared = LNRoomManager()
    static let RoomNameMinInput = 2
    static let RoomNameMaxInput = 20
    static let MicNum = 10
    static private(set) var hallEntrance = false {
        didSet {
            if oldValue != hallEntrance {
                LNEventDeliver.notifyEvent { ($0 as? LNRoomManagerNotify)?.onHallEntranceChanged() }
            }
        }
    }
    
    private(set) var roomAbility: LNRoomAbilityVO?
    private(set) weak var curRoom: LNRoomSession?
    
    let liveListStore = LiveListStore.shared
    
    init () {
        LNEventDeliver.addObserver(self)
    }
}

// MARK: 直播间管理
extension LNRoomManager {
    func getCreateRoomAbility(queue: DispatchQueue = .main,
                              handler: ((LNRoomAbilityVO?) -> Void)?)
    {
        LNHttpManager.shared.getCreateRoomAbility { info, err in
            queue.asyncIfNotGlobal {
                if let err {
                    showToast(err.errorDesc)
                    handler?(nil)
                } else {
                    self.roomAbility = info
                    handler?(info)
                    LNEventDeliver.notifyEvent { ($0 as? LNRoomManagerNotify)?.onUserRoomAbilityChanged() }
                }
            }
        }
    }
    
    func createRoom(roomName: String, cover: String, queue: DispatchQueue = .main,
                    forbidAudio: Bool, handler: @escaping (String?) -> Void)
    {
        leaveRoom { _ in
            LNHttpManager.shared.createRoom(roomTitle: roomName, roomCover: cover, forbidAudio: forbidAudio) { room, err in
                queue.asyncIfNotGlobal {
                    handler(room?.roomId)
                    LNUserDefaults[.joinedRoomId] = room?.roomId
                }
                if let err {
                    showToast(err.errorDesc)
                }
            }
        }
    }
    
    func joinRoom(roomId: String, queue: DispatchQueue = .main, handler: @escaping (String?) -> Void) {
        liveListStore.joinLive(liveID: roomId) { result in
            queue.asyncIfNotGlobal {
                switch result {
                case .success(let info):
                    handler(info.liveID)
                    LNUserDefaults[.joinedRoomId] = roomId
                case .failure(let errorInfo):
                    handler(nil)
                    showTencentError(errorInfo)
                    self.reportRoomUnavailable(id: roomId, code: errorInfo.code, reason: errorInfo.message)
                }
            }
        }
    }
    
    func closeRoom(queue: DispatchQueue = .main, handler: @escaping (Bool) -> Void) {
        liveListStore.endLive { result in
            queue.asyncIfNotGlobal {
                switch result {
                case .success:
                    handler(true)
                case .failure(let errorInfo):
                    handler(false)
                    showTencentError(errorInfo)
                }
            }
        }
    }
    
    func leaveRoom(queue: DispatchQueue = .main, handler: @escaping (Bool) -> Void) {
        let curLive: String = curRoom?.roomId ?? LNUserDefaults[.joinedRoomId, ""]
        if curLive.isEmpty {
            handler(true)
        } else {
            let json = "{\"api\":\"exitRoom\",\"params\":{\"roomId\":\"\(curLive)\",\"syncWaiting\":true,\"roomType\":2}}"
            TUIRoomEngine.sharedInstance().callExperimentalAPI(jsonStr: json) { error in
                handler(true)
                LNUserDefaults[.joinedRoomId] = ""
            }
        }
    }
    
    func updateCurRoom(_ room: LNRoomSession) {
        curRoom = room
    }
}

// MARK: 入口管理
extension LNRoomManager {
    func reloadHallEntrance() {
        LNHttpManager.shared.getHallEntrance { res, err in
            guard let res else { return }
            
            Self.hallEntrance = res.result
        }
    }
    
    func getRandomRoom(queue: DispatchQueue = .main, handler: @escaping (LNRoomItemVO?) -> Void) {
        LNHttpManager.shared.getRandomRoom { res, err in
            queue.asyncIfNotGlobal {
                handler(res?.room)
            }
            if let res, res.room?.roomId.isEmpty != false {
                Self.hallEntrance = false
            }
            if let err {
                showToast(err.errorDesc)
            }
        }
    }
    
    func searchRoom(keyword: String, next: String?, queue: DispatchQueue = .main,
                    handler: @escaping (LNSearchRoomResponse?) -> Void) {
        LNHttpManager.shared.searchRoom(keyword: keyword, size: 30, next: next ?? "") { res, err in
            queue.asyncIfNotGlobal {
                handler(res)
            }
            if let err {
                showToast(err.errorDesc)
            }
        }
    }
    
    func getRoomList(next: String?, queue: DispatchQueue = .main, handler: @escaping (LNSearchRoomResponse?) -> Void) {
        LNHttpManager.shared.getRoomList(size: 30, next: next ?? "") { res, err in
            queue.asyncIfNotGlobal {
                handler(res)
            }
            if let err {
                showToast(err.errorDesc)
            }
        }
    }
    
    func reportRoomUnavailable(id: String, code: Int, reason: String) {
        LNHttpManager.shared.reportRoomUnavailable(id: id, code: "\(code)", reason: reason) { _ in }
    }
}

// MARK: 用户
extension LNRoomManager {
    func getUserCurRoom(uid: String, queue: DispatchQueue = .main,
                        handler: @escaping (LNUserCurRoomResponse?) -> Void) {
        LNHttpManager.shared.getUserCurRoom(uid: uid) { res, err in
            queue.asyncIfNotGlobal {
                handler(res)
            }
            if let err {
                showToast(err.errorDesc)
            }
        }
    }
}

extension LNRoomManager: LNAccountManagerNotify, LNProfileManagerNotify {
    func onUserLogin() {
        getCreateRoomAbility(handler: nil)
    }
}
