//
//  SessionBaseModel.swift

//
//  Created by Leon on 2025/8/18.
//
import UIKit
import Foundation
import NIMSDK
protocol SessionCellContentDelegate {
    /// contentView 高度
    func contentSize(model: SessionBaseModel) -> CGSize
    /// 气泡在cell中的边距(外）
    func cellInsets(model: SessionBaseModel) -> UIEdgeInsets
    /// contentView距离在气泡内距离四周的边距（bubble内）
    func contentInsets(model: SessionBaseModel) -> UIEdgeInsets
    /// 是否只显示contentView， 默认false。 true时，局中显示
    func onlyShowContent(model: SessionBaseModel) -> Bool
    /// 获取当前conten View的类名
    func contentViewClass(model: SessionBaseModel) -> IMContentBaseView.Type
}

enum SessionCellType: String, Codable {
    case unknown
    case text // 普通文本消息
    case aimsg // AI Msg
    case image // 图片
    case timeStamp // 时间戳
    case create // 创建关系
    case keyword // 敏感词
    case tips // 提示
    case gift // 送礼
    case phonecall // im phone call
    case aiLoading
}

class SessionBaseModel: CustomStringConvertible, CustomDebugStringConvertible{
    /// 有气泡时，content 最大宽度
    static let maxBubbleContentWidth = floor(UIScreen.width * 0.65)
    /// 无气泡时，content 最大宽度
    static let maxContentWidth = UIScreen.width - 32
    
    var cellType: SessionCellType = .unknown

    /// Seconds timestam;
    var timeStamp: TimeInterval = 0

    var v2msg: V2NIMMessage?
    
    /// 根据message创建的数据缓存
    var baseRemoteInfo: IMBaseRemoteInfo?

    /// 是否是派生出来的model， 一般是一条消息显示两个cell中的卡片cell，本地追加创建的那种  默认NO
    var isDeriveModel = false
    /// 是否显示为卡片view
    var shouldShowCardView = false
    /// 是否显示为tips消息
    var shouldShowTips = false
    /// 是否靠左显示，根据消息发送方来确定
    var shouldShowLeft = false
    /// 默认YES，会显示气泡
    var shouldShowBubble = true

    /// 缓存高度
    var cacheCellHeight: CGFloat = 0
    /// content配置类
    var config: IMContentBaseConfig!

    var speechModel : SpeechModel?
    
    var autoPlayAudioOnce: Bool = false
    var autoPlayAlreadyPlayed : Bool = false // 已经播放过了
    
    /// 清空高度缓存
    public func clearCacheData() {
        cacheCellHeight = 0
    }
    
    public func cellHeight() -> CGFloat {
        if cacheCellHeight > 0 {
            return cacheCellHeight
        }
        // 获取content的间距
        let size = config.contentSize(model: self)
        let cellInsets = config.cellInsets(model: self)
        let contentInsets = config.contentInsets(model: self)
        // 计算高度
        let height: CGFloat = size.height + cellInsets.top + cellInsets.bottom + contentInsets.top + contentInsets.bottom
        cacheCellHeight = height
        return height
    }
    
    // MARK: Audio About
    
    func prepareAudio(info: IMAIUserInfo?,  completion:((_ model: SpeechModel?)-> Void)?){
        guard cellType == .aimsg, let text = v2msg?.text, text.count > 0, let voiceType = info?.voiceType else{
            return
        }
        
        guard AudioPlayTool.audioChannelFreeToUse() else{
            dlog("Audio Channel 不可用")
            return
        }
        
        if let path = self.speechModel?.path, path.count > 0 {
            completion?(self.speechModel)
            return
        }
        
        let saywords = String.removeBracketContents(from: text)
        guard saywords.count > 0 else{
            return
        }
        
        let speechRate = info?.dialogueSpeechRate ?? "0"
        let loudnessRate = info?.dialoguePitch ?? "0"
        
        var params = [String: Any]()
        params.updateValue(saywords, forKey: "text")
        params.updateValue(voiceType, forKey: "voiceType")
        params.updateValue(speechRate, forKey: "speechRate")
        params.updateValue(loudnessRate, forKey: "pitchRate")
        if let aiId = IMAIViewModel.shared.aiIMInfo?.aiId{
            params.updateValue(aiId, forKey: "aiId")
        }
        
        AICowProvider.request(.voiceTts(params: params), modelType: String.self) {[weak self] result in
            switch result {
            case .success(let model):
                if let audioString = model{
                    self?.speechModel = SpeechModel.modelWithBase64String(audioString)
                    //self?.speechModel?.refreshPath(path: audioString)
                    completion?(self?.speechModel)
                }
            case .failure:
                completion?(nil)
            }
        }
    }
    
    
    // MARK: - Static
    // MARK: Equatable
    static func == (lhs: SessionBaseModel, rhs: SessionBaseModel) -> Bool {
        return lhs === rhs
    }
    /// 获取不同配置类
    public static func getContentConfigClass(type: SessionCellType) -> IMContentBaseConfig.Type {
        switch type {
        case .unknown:
            return IMContentBaseConfig.self
        case .text:
            return IMTextContentConfig.self
        case .aimsg:
            return IMAIMsgContentConfig.self
        case .timeStamp:
            return IMTimeStampContentConfig.self
        case .image:
            return IMImageContentConfig.self
        case .tips, .create, .keyword:
            return IMTipsContentConfig.self
        case .gift:
            return IMGiftContentConfig.self
        case .phonecall:
            return IMPhoneCallConfig.self
        case .aiLoading:
            return IMAIMsgLoadingConfig.self
//        default:
//            return IMContentBaseConfig.self
        }
    }
    
    // MARK: - Other Debug
    var description: String {
        var attchmentString = ""
        if let attchmentRaw = v2msg?.attachment?.raw{
            attchmentString = attchmentRaw
        }
        var icon = (v2msg?.isSelf ?? false) ? "✉️" :"💌"
            
        return "\(icon)[\(cellType.rawValue)] 『\(v2msg?.text ?? "-")』raw:\(attchmentString)"
    }
    
    var debugDescription: String {
        return "[\(cellType.rawValue)] 『\(v2msg?.text ?? "-")』"
    }
}
