//
//  LNIMChatVoiceMessageCell.swift
//  Lanu
//
//  Created by OneeChan on 2025/12/5.
//

import Foundation
import UIKit
import SnapKit


class LNIMChatVoiceMessageCell: LNIMChatBaseMessageCell {
    private let voiceView = UIStackView()
    
    private let controlIc = UIImageView()
    private let waveBg = UIImageView()
    private let indicator = UIView()
    private let waveBlack = UIImageView()
    private let waveProgress = UIView()
    private let durationLabel = UILabel()
    
    private let speedView = UIView()
    private let speedLabel = UILabel()
    
    private var curItem: LNIMMessageData?
    
    private var isPlaying: Bool {
        if let content = curItem?.content,
           content.lowercased().starts(with: "http") {
            return LNVoicePlayer.shared.playingUrl == content
        }
        
        guard let playingUrl = LNVoicePlayer.shared.playingUrl else {
            return false 
        }
        return playingUrl == curItem?.imMessage.soundElem?.uuid
    }
    
    override func update(_ data: LNIMMessageData, viewModel: LNIMChatViewModel) {
        super.update(data, viewModel: viewModel)
        
        curItem = data
        if data.imMessage.isSelf {
            waveBg.image = .icImChatMyVoice
            waveBlack.image = .icImChatMyVoiceBlack
        } else {
            waveBg.image = .icImChatPeerVoice
            waveBlack.image = .icImChatPeerVoiceBlack
        }
        
        if isPlaying {
            updatePlayUI()
        } else {
            updateStopUI()
        }
        
        LNEventDeliver.addObserver(self)
    }
    
    private func updatePlayUI(animated: Bool = false) {
        guard let curItem else { return }
        controlIc.image = .icImChatVoicePause
        
        let currentTime = LNVoicePlayer.shared.currentTime + 0.25
        let duration = LNVoicePlayer.shared.duration
        durationLabel.text = .init(format: "%02d:%02d", Int(currentTime) / 60, Int(currentTime) % 60)
        
        if curItem.imMessage.isSelf {
            indicator.backgroundColor = .text_3
        } else {
            indicator.backgroundColor = .primary_3
        }
        waveProgress.snp.remakeConstraints { make in
            make.leading.verticalEdges.equalTo(waveBg)
            if duration == 0 || currentTime == 0 {
                make.width.equalTo(0)
            } else {
                make.width.equalTo(waveBg).multipliedBy(currentTime / Double(duration))
            }
        }
        if speedView.superview == nil {
            voiceView.addArrangedSubview(speedView)
        }
        speedLabel.text = "\(Int(LNVoicePlayer.shared.curSpeed))x"
        if animated {
            UIView.animate(withDuration: 0.25) { [weak self] in
                guard let self else { return }
                waveProgress.superview?.layoutIfNeeded()
            }
        }
    }
    
    private func updateStopUI() {
        guard let curItem else { return }
        controlIc.image = .icImChatVoicePlay
        
        durationLabel.text = .init(format: "%02d:%02d", curItem.voiceDuration / 60, curItem.voiceDuration % 60)
        
        if curItem.imMessage.isSelf {
            indicator.backgroundColor = .text_3
        } else {
            indicator.backgroundColor = .init(hex: "#1789FF")
        }
        waveProgress.snp.remakeConstraints { make in
            make.leading.verticalEdges.equalTo(waveBg)
            make.width.equalTo(0)
        }
        
        voiceView.removeArrangedSubview(speedView)
        speedView.removeFromSuperview()
    }
    
    override func setupViews() {
        LNEventDeliver.addObserver(self)
        
        super.setupViews()
        
        voiceView.axis = .horizontal
        voiceView.spacing = 8
        container.addSubview(voiceView)
        voiceView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        controlIc.isUserInteractionEnabled = false
        voiceView.addArrangedSubview(controlIc)
        
        voiceView.addArrangedSubview(waveBg)
        
        waveProgress.clipsToBounds = true
        waveBg.addSubview(waveProgress)
        waveProgress.snp.makeConstraints { make in
            make.leading.verticalEdges.equalToSuperview()
            make.width.equalTo(0)
        }
        
        waveProgress.addSubview(waveBlack)
        waveBlack.snp.makeConstraints { make in
            make.leading.verticalEdges.equalToSuperview()
        }
        
        indicator.backgroundColor = .text_3
        indicator.layer.cornerRadius = 5
        waveBg.addSubview(indicator)
        indicator.snp.makeConstraints { make in
            make.centerX.equalTo(waveProgress.snp.trailing)
            make.centerY.equalToSuperview()
            make.width.height.equalTo(10)
        }
        
        durationLabel.font = .body_xs
        durationLabel.textColor = .text_3
        container.addSubview(durationLabel)
        durationLabel.snp.makeConstraints { make in
            make.leading.equalTo(waveBg)
            make.top.equalTo(container.snp.bottom).offset(4)
        }
        
        speedView.backgroundColor = .text_5.withAlphaComponent(0.4)
        speedView.layer.cornerRadius = 14
        speedView.snp.makeConstraints { make in
            make.height.equalTo(28)
        }
        speedLabel.font = .body_m
        speedLabel.textColor = .text_1
        speedView.addSubview(speedLabel)
        speedLabel.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.leading.greaterThanOrEqualToSuperview().offset(17.5)
        }
        
        speedView.onTap { [weak self] in
            guard self != nil else { return }
            if LNVoicePlayer.shared.curSpeed == 1.0 {
                LNVoicePlayer.shared.setSpeed(speed: 2.0)
            } else {
                LNVoicePlayer.shared.setSpeed(speed: 1.0)
            }
        }
        
        container.onTap { [weak self] in
            guard let self else { return }
            guard let curItem else { return }
            if let content = curItem.content,
               content.lowercased().starts(with: "http") {
                if LNVoicePlayer.shared.playingUrl == content {
                    LNVoicePlayer.shared.stop()
                } else {
                    LNVoicePlayer.shared.play(content)
                }
                return
            }
            if LNVoicePlayer.shared.playingUrl == curItem.imMessage.soundElem?.uuid {
                LNVoicePlayer.shared.stop()
                return
            }
            LNVoicePlayer.shared.playVoiceMessage(message: curItem)
        }
    }
}

extension LNIMChatVoiceMessageCell: LNVoicePlayerNotify {
    func onAudioStartPlay(path: String) {
        guard isPlaying else { return }
        updatePlayUI(animated: true)
    }
    
    func onAudioUpdateDuration(path: String, cur: TimeInterval, total: TimeInterval) {
        guard isPlaying else { return }
        updatePlayUI(animated: true)
    }
    
    func onAudioStopPlay(path: String) {
        guard isPlaying else { return }
        updateStopUI()
    }
}
