//
//  RoleVoiceAdjustView.swift

//
//  Created by Leon on 2025/7/21.
//

import UIKit
import Combine
class RoleVoiceAdjustView: UIView {
    var titleLabel: UILabel!
    var closeButton: EPIconTertiaryButton!
    
    var toneTipLabel: UILabel!
    var toneSlider: CustomSlider!

    var speedTipLabel: UILabel!
    var speedSlider: CustomSlider!

    var bottomStackH: UIStackView!
    var playButton: AudioButton!
    var playTipLabel: UILabel!
    var playTopButton : UIButton!

//    var tapPlayButtonBlock: (() -> Void)?
    
    var tapCloseButtonBlock: (() -> Void)?
    
    // Data
    
    var voice: VoiceModel?
    
    var speechModel : SpeechModel?
    /// 音高
    var speechLoudness: Int = 0  // 改为0，对应中间值
    /// 语速
    var speechRate: Int = 25
    
    /// 音高
    var audioNowSpeechPitch : Int?
    /// 语速
    var audioNowSpeechSpeed : Int?
    
    
//    var adjustVoice: Bool = false
    private var cancellables = Set<AnyCancellable>()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupViews() {
        backgroundColor = UIColor.c.csbn
        layer.cornerRadius = 16
        layer.masksToBounds = true

        titleLabel = {
            let v = UILabel()
            v.textColor = .c.ctpn
            v.font = .t.tlm
            addSubview(v)
            v.snp.makeConstraints { make in
                make.top.equalToSuperview().offset(18)
                make.leading.equalToSuperview().offset(16)
            }
            return v
        }()

        closeButton = {
            let v = EPIconTertiaryButton(radius: .round, iconSize: .xs, iconCode: .delete)
            v.addTarget(self, action: #selector(tapCloseButton), for: .touchUpInside)
            addSubview(v)
            v.snp.makeConstraints { make in
                make.top.equalToSuperview().offset(18)
                make.trailing.equalToSuperview().offset(-16)
            }
            return v
        }()
        
        toneTipLabel = {
            let v = UILabel()
            v.textColor = .c.ctsn
            v.font = .t.tls
            addSubview(v)
            v.snp.makeConstraints { make in
                make.leading.equalToSuperview().offset(16)
                make.top.equalTo(titleLabel.snp.bottom).offset(18)
            }
            v.text = "Low"
            
            let high = {
                let v = UILabel()
                v.textColor = .c.ctsn
                v.font = .t.tls
                addSubview(v)
                v.snp.makeConstraints { make in
                    make.trailing.equalToSuperview().offset(-16)
                    make.top.equalTo(titleLabel.snp.bottom).offset(18)
                }
                v.text = "High"
                return v
            }()
            high.isHidden = false
            
            return v
        }()
        
        toneSlider = {
            let v = CustomSlider()
            addSubview(v)
            v.numberOfSteps = 11
            v.selectedStep = 5
            v.translatesAutoresizingMaskIntoConstraints = false
            v.snp.makeConstraints { make in
                make.leading.equalToSuperview().offset(16)
                make.trailing.equalToSuperview().offset(-16)
                //make.top.equalTo(titleLabel.snp.bottom).offset(42)
                make.top.equalTo(toneTipLabel.snp.bottom).offset(4)
                make.height.equalTo(44)
            }
            return v
        }()

        speedTipLabel = {
            let v = UILabel()
            v.textColor = .c.ctsn
            v.font = .t.tls
            addSubview(v)
            v.snp.makeConstraints { make in
                make.leading.equalToSuperview().offset(16)
                make.top.equalTo(toneSlider.snp.bottom).offset(18)
            }
            v.text = "Slow"

            let high = {
                let v = UILabel()
                v.textColor = .c.ctsn
                v.font = .t.tls
                addSubview(v)
                v.snp.makeConstraints { make in
                    make.trailing.equalToSuperview().offset(-16)
                    make.top.equalTo(toneSlider.snp.bottom).offset(18)
                }
                v.text = "Fast"
                return v
            }()
            high.isHidden = false

            return v
        }()

        speedSlider = {
            let v = CustomSlider()
            addSubview(v)
            v.numberOfSteps = 11
            v.selectedStep = 5
            v.translatesAutoresizingMaskIntoConstraints = false
            v.snp.makeConstraints { make in
                make.leading.equalToSuperview().offset(16)
                make.trailing.equalToSuperview().offset(-16)
                make.top.equalTo(speedTipLabel.snp.bottom).offset(4)
                make.height.equalTo(44)
            }
            return v
        }()

        bottomStackH = {
            let v = UIStackView()
            v.axis = .horizontal
            v.spacing = 12
            v.alignment = .center
            addSubview(v)
            v.snp.makeConstraints { make in
                make.top.equalToSuperview().offset(224)
                make.centerX.equalToSuperview()
                make.bottom.equalToSuperview().offset(-16)
                make.height.equalTo(40)
            }
            return v
        }()
        
        playButton = {
            let v = AudioButton(style: .voiceThemePlay, size: .square24)
            v.addTarget(self, action: #selector(tapPlayButton), for: .touchUpInside)
            bottomStackH.addArrangedSubview(v)
            v.snp.makeConstraints { make in
                make.centerY.equalToSuperview()
                make.leading.equalToSuperview().offset(16)
            }
            return v
        }()

        playTipLabel = {
            let v = UILabel()
            v.font = .t.tll
            v.textColor = .c.cpvn
            bottomStackH.addArrangedSubview(v)
            v.snp.makeConstraints { make in
                make.height.equalTo(24)
            }
            return v
        }()
        
        playTopButton = {
            let v = UIButton()
            addSubview(v)
            v.addTarget(self, action: #selector(tapPlayButton), for: .touchUpInside)
            v.snp.makeConstraints { make in
                make.edges.equalTo(bottomStackH)
            }
            return v
        }()
        
        speedSlider.$selectedStep.sink {[weak self] step in
            
            // 11 steps[0~10], -50 to 100
            let speed = -50 + step * 15
            self?.speechRate = speed
            dlog("speed step:\(step), speed:\(speed)")
        }.store(in: &cancellables)
        
        toneSlider.$selectedStep.sink {[weak self] step in
            
            // 11 steps[0~10], -12 to 12
            let loudness = -12 + Float(step) * 2.4
            let loudnessInt = Int(round(loudness))
            self?.speechLoudness = loudnessInt
            dlog("pitch step:\(step), loundess:\(loudnessInt)")
        }.store(in: &cancellables)
        
        // titleLabel.text = "Young Male Voice"
        playTipLabel.text = "Tap to play"
    }
    
    // MARK: - Public
    public func bind(voice: VoiceModel?){
        if let newVoice = voice, let voiceType = newVoice.voiceDict.voiceType{
            if let beforeVoiceType = self.voice?.voiceDict.voiceType, voiceType != beforeVoiceType{
                dlog("select new type voice.")
                speechModel = nil
            }
            
            self.voice = newVoice
            // 兼容老数据：-50~100 映射到 -12~12
            if let pitch = voice?.dialoguePitch, let pitchInt = Int(pitch){
                // 老数据范围：-50~100，新数据范围：-12~12
                var normalizedPitch: Int
                if pitchInt > 12 {
                    normalizedPitch = 12
                } else if pitchInt < -12{
                    normalizedPitch = -12
                }
                else {
                    // 新数据直接使用
                    normalizedPitch = pitchInt
                }
                
                // 将音高值映射到滑块步骤
                let step = Int(round((Double(normalizedPitch) - (-12)) / 2.4))
                let clampedStep = max(0, min(10, step))
                toneSlider.selectedStep = clampedStep
            }
            
            if let speed = voice?.dialogueSpeechRate, let speedInt = Int(speed){
                // get closest step
                let step = Int((speedInt + 50) / 15)
                speedSlider.selectedStep = step
            }
        }
        
        
    }
    
    
    // MARK: - Helper
    
    func prepareAudio(content: String?,  completion:((_ model: SpeechModel?)-> Void)?){
//        #warning("test")
//        playButton.startIndicator()
//        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
//            completion?(SpeechModel())
//        }
//        return
        
        guard let text = content, text.count > 0, let voiceType = voice?.voiceDict.voiceType else{
            return
        }
        
        guard AudioPlayTool.audioChannelFreeToUse() else{
            dlog("Audio Channel 不可用")
            return
        }
        
        let saywords = String.removeBracketContents(from: text)
        guard saywords.count > 0 else{
            return
        }
        
        let speechRate = self.speechRate
        let loudnessRate = self.speechLoudness
        
        var params = [String: Any]()
        params.updateValue(saywords, forKey: "text")
        params.updateValue(voiceType, forKey: "voiceType")
        params.updateValue(speechRate, forKey: "speechRate")
        params.updateValue(loudnessRate, forKey: "pitchRate")
        
        playButton.startIndicator()
        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)
                    completion?(self?.speechModel)
                }
            case .failure:
                Hud.hideIndicator()
                completion?(SpeechModel())
            }
        }
    }

    // MARK: - Action
    @objc func tapPlayButton() {
        dlog("play audio, speechRate: \(speechRate), speechLoudness: \(speechLoudness)")

        if let speechModel = self.speechModel, let pitch = audioNowSpeechPitch, let speed = audioNowSpeechSpeed, pitch == speechRate, speed == speechLoudness {
            playButton.reloadState(with: speechModel)
            SpeechManager.shared.startPlay(with: speechModel)
        }else{
            speechModel = nil
            let voiceText = voice?.voiceDict.voiceText ?? "我是来自北方的一匹孤星的狼"
            prepareAudio (content: voiceText) {[weak self] model in
                if let speechModel = model{
                    self?.audioNowSpeechPitch = self?.speechLoudness
                    self?.audioNowSpeechSpeed = self?.speechRate
                    
                    self?.playButton.reloadState(with: speechModel)
                    SpeechManager.shared.startPlay(with: speechModel)
                }
                else{
                    // self?.playButton.reloadState(with: nil)
                    assert(false, "cannot return nil")
                }
            }
        }
    }
    
    @objc func tapCloseButton() {
        tapCloseButtonBlock?()
    }
}
