//
//  LNAudioCallPanel.swift
//  Gami
//
//  Created by OneeChan on 2026/2/1.
//

import Foundation
import UIKit
import SnapKit


class LNAudioCallPanel: LNPopupView {
    private let background = UIImageView()
    
    private let avatar = UIImageView()
    private let nameLabel = UILabel()
    
    private let orderView = UIView()
    private let gameIc = UIImageView()
    private let orderStateLabel = UILabel()
    private let orderTimeLabel = UILabel()
    private let gameNameLabel = UILabel()
    private let gameCountLabel = UILabel()
    
    private let stateLabel = UILabel()
    
    private let onCallView = UIView()
    private let callOutView = UIView()
    
    private let callingView = UIView()
    private let durationLabel = UILabel()
    private let muteButton = UIButton()
    private let speakerButton = UIButton()
    
    private var timer: Timer?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupViews()
        LNEventDeliver.addObserver(self)
    }
    
    func toCallOut(uid: String) {
        callOutView.isHidden = false
        stateLabel.isHidden = false
        reloadUserInfo(uid: uid)
    }
    
    func onCallIn(uid: String) {
        onCallView.isHidden = false
        stateLabel.isHidden = false
        reloadUserInfo(uid: uid)
    }
    
    func resume() {
        guard let callInfo = LNIMManager.shared.curCallInfo else { return }
        if callInfo.beginTime > 0 {
            updateCallDuration()
            startTimer()
            callingView.isHidden = false
            stateLabel.isHidden = true
            getCurOrders(uid: callInfo.uid)
        } else if callInfo.isInCome {
            onCallView.isHidden = false
            stateLabel.isHidden = false
        } else {
            callOutView.isHidden = false
            stateLabel.isHidden = false
        }
        
        reloadUserInfo(uid: callInfo.uid)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension LNAudioCallPanel {
    private func reloadUserInfo(uid: String) {
        LNProfileManager.shared.getUserProfileDetail(uid: uid) { [weak self] info in
            guard let self else { return }
            guard let info else { return }
            background.showAvatar(info.avatar)
            avatar.showAvatar(info.avatar)
            nameLabel.text = info.nickname
        }
    }
    
    private func getCurOrders(uid: String) {
        LNOrderManager.shared.getUnfinishedOrderWith(uid: uid, size: 1, next: nil) { [weak self] list, _ in
            guard let self else { return }
            guard let order = list?.first else { return }
            
            avatar.layer.cornerRadius = 60
            avatar.snp.updateConstraints { make in
                make.width.height.equalTo(120)
            }
            orderView.isHidden = false
            gameIc.sd_setImage(with: URL(string: order.categoryIcon))
            gameNameLabel.text = order.bizCategoryName
            orderTimeLabel.text = Double(order.createTime / 1_000).formattedFullDateWithTime()
            gameCountLabel.text = "x \(order.purchaseQty) \(order.unit)"
            orderStateLabel.text = order.statusUI.title
        }
    }
    
    private func updateCallDuration() {
        guard let callInfo = LNIMManager.shared.curCallInfo else { return }
        let duration = curTime - callInfo.beginTime
        durationLabel.text = duration.timeCountDisplay
    }
    
    private func startTimer() {
        stopTimer()
        let timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] _ in
            guard let self else { return }
            guard LNIMManager.shared.curCallInfo != nil else {
                stopTimer()
                return
            }
            
            updateCallDuration()
        }
        RunLoop.main.add(timer, forMode: .common)
        self.timer = timer
    }
    
    private func stopTimer() {
        timer?.invalidate()
        timer = nil
    }
}

extension LNAudioCallPanel: LNIMManagerNotify {
    func onVoiceCallBegin() {
        onCallView.isHidden = true
        callOutView.isHidden = true
        callingView.isHidden = false
        stateLabel.isHidden = true
        
        updateCallDuration()
        startTimer()
        
        if let callInfo = LNIMManager.shared.curCallInfo {
            getCurOrders(uid: callInfo.uid)
        }
    }
    
    func onVoiceCallEnd() {
        dismiss()
        stopTimer()
    }
    
    func onVoiceCallInfoChanged() {
        guard let callInfo = LNIMManager.shared.curCallInfo else { return }
        muteButton.setImage(callInfo.isMute ? .icCallMute : .icCallUnmute, for: .normal)
        let icon: UIImage = if callInfo.deviceType == .earpiece {
            .icCallSpeakerEarpiece
        } else {
            .icCallSpeakerPhone
        }
        speakerButton.setImage(icon, for: .normal)
    }
}

extension LNAudioCallPanel {
    private func setupViews() {
        containerHeight = .percent(1.0)
        
        let background = buildBackground()
        container.addSubview(background)
        background.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        let navBar = buildNavBar()
        container.addSubview(navBar)
        navBar.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.top.equalToSuperview()
        }
        
        let infoView = buildInfoView()
        container.addSubview(infoView)
        infoView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview().inset(16)
            make.top.greaterThanOrEqualTo(navBar.snp.bottom).offset(16)
            make.bottom.equalTo(container.snp.centerY).offset(-30).priority(.medium)
        }
        
        stateLabel.text = .init(key: "C00015")
        stateLabel.font = .body_xl
        stateLabel.textColor = .text_2
        container.addSubview(stateLabel)
        stateLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(infoView.snp.bottom)
        }
        
        let onCallView = buildOnCallView()
        container.addSubview(onCallView)
        onCallView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview().inset(48)
            make.bottom.equalToSuperview().offset(-100)
        }
        
        let callOutView = buildCallOutView()
        container.addSubview(callOutView)
        callOutView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview().inset(48)
            make.bottom.equalToSuperview().offset(-100)
        }
        
        let callingView = buildCallingView()
        container.addSubview(callingView)
        callingView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview().inset(48)
            make.bottom.equalToSuperview().offset(-100)
        }
    }
    
    private func buildBackground() -> UIView {
        background.backgroundColor = .lightGray
        background.contentMode = .scaleAspectFill
        
        let blurEffect = UIBlurEffect(style: .light)
        let blurView = UIVisualEffectView(effect: blurEffect)
        background.addSubview(blurView)
        blurView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
//         可选：添加半透明遮罩，增强模糊层次感（毛玻璃常用搭配）
        let maskView = UIView(frame: blurView.bounds)
        maskView.backgroundColor = UIColor.black.withAlphaComponent(0.3) // 0.1~0.3为宜
        blurView.contentView.addSubview(maskView)
        maskView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        return background
    }
    
    private func buildNavBar() -> UIView {
        let navBar = LNFakeNaviBar()
        
        let minButton = UIButton()
        minButton.setImage(.icCallMin, for: .normal)
        minButton.addAction(UIAction(handler: { [weak self] _ in
            guard let self else { return }
            dismiss()
        }), for: .touchUpInside)
        navBar.actionView.addSubview(minButton)
        minButton.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(16)
            make.centerY.equalToSuperview()
            make.width.height.equalTo(38)
        }
        
        return navBar
    }
    
    private func buildInfoView() -> UIView {
        let container = UIView()
        
        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.alignment = .center
        stackView.spacing = 4
        container.addSubview(stackView)
        stackView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        avatar.layer.cornerRadius = 75
        avatar.clipsToBounds = true
        avatar.snp.makeConstraints { make in
            make.width.height.equalTo(150)
        }
        stackView.addArrangedSubview(avatar)
        
        nameLabel.font = .heading_h1
        nameLabel.textColor = .text_1
        stackView.addArrangedSubview(nameLabel)
        
        let orderView = buildOrderView()
        stackView.addArrangedSubview(orderView)
        orderView.snp.makeConstraints { make in
            make.width.equalToSuperview()
        }
        
        return container
    }
    
    private func buildOrderView() -> UIView {
        orderView.backgroundColor = .fill.withAlphaComponent(0.5)
        orderView.layer.cornerRadius = 12
        orderView.isHidden = true
        
        orderView.addSubview(gameIc)
        gameIc.snp.makeConstraints { make in
            make.top.equalToSuperview()
            make.leading.equalToSuperview().offset(10)
            make.width.height.equalTo(50)
        }
        
        let infoView = UIView()
        orderView.addSubview(infoView)
        infoView.snp.makeConstraints { make in
            make.centerY.equalTo(gameIc)
            make.leading.equalTo(gameIc.snp.trailing).offset(2)
            make.trailing.equalToSuperview().offset(-10)
        }
        
        orderStateLabel.font = .heading_h4
        orderStateLabel.textColor = .text_5
        infoView.addSubview(orderStateLabel)
        orderStateLabel.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.top.equalToSuperview()
        }
        
        orderTimeLabel.font = .body_xs
        orderTimeLabel.textColor = .text_4
        infoView.addSubview(orderTimeLabel)
        orderTimeLabel.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.bottom.equalToSuperview()
            make.top.equalTo(orderStateLabel.snp.bottom).offset(2)
        }
        
        let line = UIView()
        line.backgroundColor = .fill_4
        orderView.addSubview(line)
        line.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview().inset(12)
            make.height.equalTo(0.5)
            make.bottom.equalTo(gameIc)
        }
        
        let gameInfo = UIView()
        orderView.addSubview(gameInfo)
        gameInfo.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.top.equalTo(gameIc.snp.bottom)
            make.bottom.equalToSuperview()
            make.height.equalTo(30)
        }
        
        gameNameLabel.font = .body_s
        gameNameLabel.textColor = .text_4
        gameInfo.addSubview(gameNameLabel)
        gameNameLabel.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(16)
        }
        
        gameCountLabel.font = .body_s
        gameCountLabel.textColor = .text_4
        gameCountLabel.setContentHuggingPriority(.required, for: .horizontal)
        gameCountLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
        gameInfo.addSubview(gameCountLabel)
        gameCountLabel.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.trailing.equalToSuperview().offset(-16)
            make.leading.greaterThanOrEqualTo(gameNameLabel.snp.trailing).offset(16)
        }
        
        return orderView
    }
    
    private func buildOnCallView() -> UIView {
        onCallView.isHidden = true
        
        let stackView = UIStackView()
        stackView.distribution = .equalSpacing
        onCallView.addSubview(stackView)
        stackView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        let rejectButton = UIButton()
        rejectButton.setImage(.icCallDecline, for: .normal)
        rejectButton.addAction(UIAction(handler: { _ in
            LNIMManager.shared.rejectVoiceCall()
        }), for: .touchUpInside)
        stackView.addArrangedSubview(rejectButton)
        
        let acceptButton = UIButton()
        acceptButton.setImage(.icCallAccept, for: .normal)
        acceptButton.addAction(UIAction(handler: { _ in
            LNIMManager.shared.acceptVoiceCall()
        }), for: .touchUpInside)
        stackView.addArrangedSubview(acceptButton)
        
        return onCallView
    }
    
    private func buildCallOutView() -> UIView {
        callOutView.isHidden = true
        
        let cancelButton = UIButton()
        cancelButton.setImage(.icCallDecline, for: .normal)
        cancelButton.addAction(UIAction(handler: { _ in
            LNIMManager.shared.hangupVoiceCall()
        }), for: .touchUpInside)
        callOutView.addSubview(cancelButton)
        cancelButton.snp.makeConstraints { make in
            make.verticalEdges.equalToSuperview()
            make.centerX.equalToSuperview()
        }
        
        return callOutView
    }
    
    private func buildCallingView() -> UIView {
        callingView.isHidden = true
        
        let stackView = UIStackView()
        stackView.alignment = .center
        stackView.distribution = .equalSpacing
        callingView.addSubview(stackView)
        stackView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.bottom.equalToSuperview()
        }
        
        muteButton.setImage(.icCallUnmute, for: .normal)
        muteButton.addAction(UIAction(handler: { _ in
            LNIMManager.shared.switchVoiceCallMicrophone()
        }), for: .touchUpInside)
        stackView.addArrangedSubview(muteButton)
        
        let hangupButton = UIButton()
        hangupButton.setImage(.icCallDecline, for: .normal)
        hangupButton.addAction(UIAction(handler: { _ in
            LNIMManager.shared.hangupVoiceCall()
        }), for: .touchUpInside)
        stackView.addArrangedSubview(hangupButton)
        
        speakerButton.setImage(.icCallSpeakerEarpiece, for: .normal)
        speakerButton.addAction(UIAction(handler: { _ in
//            if DevicesUtil.isBluetoothHeadsetConnected {
//                let menu = LNVoiceCallSpeakerSelectPopoverMenu()
//                menu.pointAt(parentView: self, targetView: speakerButton) { type in
//                    LNIMManager.shared.switchVoiceCallSpeakerType(type: type)
//                }
//            } else
            if let callInfo = LNIMManager.shared.curCallInfo {
                if callInfo.deviceType == .speakerphone {
                    LNIMManager.shared.switchVoiceCallSpeakerType(type: .earpiece)
                } else {
                    LNIMManager.shared.switchVoiceCallSpeakerType(type: .speakerphone)
                }
            }
        }), for: .touchUpInside)
        stackView.addArrangedSubview(speakerButton)
        
        durationLabel.font = .body_l
        durationLabel.textColor = .text_1
        callingView.addSubview(durationLabel)
        durationLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalToSuperview()
            make.bottom.equalTo(stackView.snp.top).offset(-14)
        }
        
        return callingView
    }
}


private class LNVoiceCallSpeakerSelectPopoverMenu: UIView {
    private let holder = UIView()
    private var handler: ((LNIMVoiceCallSpeakerType) -> Void)?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        let touchView = UIView()
        touchView.onTap { [weak self] in
            guard let self else { return }
            dismiss()
        }
        addSubview(touchView)
        touchView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        holder.backgroundColor = .fill.withAlphaComponent(0.8)
        holder.layer.cornerRadius = 10
        addSubview(holder)
        
        let stackView = UIStackView()
        stackView.axis = .vertical
        holder.addSubview(stackView)
        stackView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview().inset(4)
            make.top.equalToSuperview().offset(4)
            make.bottom.equalToSuperview().offset(-10)
        }
        
        let device = LNIMManager.shared.curCallInfo?.deviceType
        
        let bluetooth = buildMenuItem(ic: .icCallDeviceBluetooth, title: .init(key: "C00008"), isCheck: device == .bluetooth)
        bluetooth.onTap { [weak self] in
            guard let self else { return }
            dismiss()
            handler?(.bluetooth)
        }
        stackView.addArrangedSubview(bluetooth)
        
        let ear = buildMenuItem(ic: .icCallDeviceEar, title: .init(key: "C00006"), isCheck: device == .earpiece)
        ear.onTap { [weak self] in
            guard let self else { return }
            dismiss()
            handler?(.earpiece)
        }
        stackView.addArrangedSubview(ear)
        
        let speaker = buildMenuItem(ic: .icCallDeviceSpeaker, title: .init(key: "C00007"), isCheck: device == .speakerphone)
        speaker.onTap { [weak self] in
            guard let self else { return }
            dismiss()
            handler?(.speakerphone)
        }
        stackView.addArrangedSubview(speaker)
        
        let triangle = UIImageView()
        triangle.image = .icTriangleDown
        triangle.alpha = 0.8
        addSubview(triangle)
        triangle.snp.makeConstraints { make in
            make.centerX.equalTo(holder)
            make.top.equalTo(holder.snp.bottom)
        }
    }
    
    func pointAt(parentView: UIView, targetView: UIView, handler: @escaping (LNIMVoiceCallSpeakerType) -> Void) {
        parentView.addSubview(self)
        snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        holder.snp.makeConstraints { make in
            make.centerX.equalTo(targetView)
            make.bottom.equalTo(targetView.snp.top).offset(-8)
        }
        
        self.handler = handler
    }
    
    func dismiss() {
        removeFromSuperview()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func buildMenuItem(ic: UIImage, title: String, isCheck: Bool) -> UIView {
        let container = UIView()
        container.snp.makeConstraints { make in
            make.height.equalTo(38)
            make.width.equalTo(124)
        }
        
        let icon = UIImageView(image: ic)
        container.addSubview(icon)
        icon.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(6)
        }
        
        let titleLabel = UILabel()
        titleLabel.font = .body_m
        titleLabel.textColor = isCheck ? .text_5 : .text_4
        titleLabel.text = title
        container.addSubview(titleLabel)
        titleLabel.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalTo(icon.snp.trailing).offset(8)
        }
        
        if isCheck {
            let checkIc = UIImageView(image: .icCheckBlack)
            container.addSubview(checkIc)
            checkIc.snp.makeConstraints { make in
                make.centerY.equalToSuperview()
                make.trailing.equalToSuperview().offset(-6)
                make.leading.greaterThanOrEqualTo(titleLabel.snp.trailing).offset(2)
            }
        }
        
        return container
    }
}

#if DEBUG

import SwiftUI

struct LNVoiceCallPanelPreview: UIViewRepresentable {
    func makeUIView(context: Context) -> some UIView {
        let container = UIView()
        container.backgroundColor = .lightGray
        
        let view = LNAudioCallPanel()
        view.popup()
        
        return container
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) { }
}

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

