//
//  LNIMChatVoiceInputView.swift
//  Lanu
//
//  Created by OneeChan on 2025/12/4.
//

import Foundation
import UIKit
import SnapKit


protocol LNIMChatVoiceInputViewDelegate: AnyObject {
    func onVoiceFinishInput()
}


class LNIMChatVoiceInputView: UIView {
    private let durationLabel = UILabel()
    private let waveView = LNIMChatVoiceWaveView()
    
    private let controlButton = UIButton()
    private var recordTaskId: String?
    
    private let maxRecord: Double = 60
    
    weak var delegate: LNIMChatVoiceInputViewDelegate?
    weak var viewModel: LNIMChatViewModel?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupViews()
        
        LNEventDeliver.addObserver(self)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension LNIMChatVoiceInputView {
    func startRecord() {
        LNVoicePlayer.shared.stop()
        LNVoiceRecorder.shared.startRecord(maxRecord) { [weak self] taskId in
            guard let self else { return }
            recordTaskId = taskId
        }
    }
}

extension LNIMChatVoiceInputView: LNVoiceRecorderNotify {
    func onRecordTaskReachMaxDuration(taskId: String, fileUrl: URL?, duration: Double) {
        if let fileUrl {
            viewModel?.sendVoiceMessage(voicePath: fileUrl.path, duration: duration)
        }
    }
    
    func onRecordTaskStop(taskId: String) {
        guard taskId == recordTaskId else { return }
        controlButton.setImage(.icImChatVoiceInputPause, for: .normal)
        durationLabel.text = "00:00"
        
        waveView.clear()
        delegate?.onVoiceFinishInput()
    }
    
    func onRecordTaskPause(taskId: String) {
        guard taskId == recordTaskId else { return }
        controlButton.setImage(.icImChatVoiceInputContinue, for: .normal)
    }
    
    func onRecordTaskDurationChanged(taskId: String, duration: Double, volumeRatio: Double) {
        guard taskId == recordTaskId else { return }
        durationLabel.text = .init(format: "%02d:%02d", Int(duration) / 60, Int(duration) % 60)
        waveView.add(volumeRatio)
    }
    
    func onRecordTaskRecording(taskId: String) {
        guard taskId == recordTaskId else { return }
        controlButton.setImage(.icImChatVoiceInputPause, for: .normal)
    }
}

extension LNIMChatVoiceInputView {
    private func setupViews() {
        backgroundColor = .fill
        let infoView = buildVoiceInfoView()
        addSubview(infoView)
        infoView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.top.equalToSuperview()
        }
        
        let controlView = buildVoiceControlView()
        addSubview(controlView)
        controlView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.bottom.equalToSuperview().offset(-safeBottomInset)
            make.top.equalTo(infoView.snp.bottom)
        }
    }
    
    private func buildVoiceInfoView() -> UIView {
        let container = UIView()
        container.snp.makeConstraints { make in
            make.height.equalTo(40)
        }
        
        durationLabel.font = .heading_h2
        durationLabel.textColor = .text_5
        durationLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal)
        durationLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
        container.addSubview(durationLabel)
        durationLabel.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(16)
        }
        
        container.addSubview(waveView)
        waveView.snp.makeConstraints { make in
            make.trailing.equalToSuperview().offset(-16)
            make.leading.equalToSuperview().offset(82)
            make.height.equalTo(28)
            make.centerY.equalToSuperview()
        }
        
        return container
    }
    
    private func buildVoiceControlView() -> UIView {
        let container = UIView()
        container.snp.makeConstraints { make in
            make.height.equalTo(40)
        }
        
        let deleteButton = UIButton()
        deleteButton.setImage(.icImChatVoiceInputDelete, for: .normal)
        deleteButton.addAction(UIAction(handler: { [weak self] _ in
            guard let self else { return }
            delegate?.onVoiceFinishInput()
            LNVoiceRecorder.shared.stopRecord()
            waveView.clear()
        }), for: .touchUpInside)
        container.addSubview(deleteButton)
        deleteButton.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(12)
        }
        
        controlButton.setImage(.icImChatVoiceInputPause, for: .normal)
        controlButton.addAction(UIAction(handler: { [weak self] _ in
            guard self != nil else { return }
            if LNVoiceRecorder.shared.curState == .recording {
                LNVoiceRecorder.shared.pauseRecord()
            } else if LNVoiceRecorder.shared.curState == .pausing {
                LNVoiceRecorder.shared.continueRecord()
            }
        }), for: .touchUpInside)
        container.addSubview(controlButton)
        controlButton.snp.makeConstraints { make in
            make.center.equalToSuperview()
        }
        
        let sendButton = UIButton()
        sendButton.setImage(.icImChatSend, for: .normal)
        sendButton.addAction(UIAction(handler: { [weak self] _ in
            guard let self else { return }
            let (path, duration) = LNVoiceRecorder.shared.stopRecord()
            
            if let path {
                viewModel?.sendVoiceMessage(voicePath: path.path, duration: duration)
            }
        }), for: .touchUpInside)
        container.addSubview(sendButton)
        sendButton.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.trailing.equalToSuperview().offset(-12)
        }
        
        return container
    }
}

#if DEBUG

import SwiftUI

struct LNIMChatVoiceInputViewPreview: UIViewRepresentable {
    func makeUIView(context: Context) -> some UIView {
        let container = UIView()
        container.backgroundColor = .lightGray
        
        let view = LNIMChatVoiceInputView()
        container.addSubview(view)
        view.snp.makeConstraints { make in
            make.leading.trailing.bottom.equalToSuperview()
        }
        
        return container
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) { }
}

#Preview(body: {
    LNIMChatVoiceInputViewPreview()
})
#endif
