//
//  VehicleMonitorHistoryController.swift
//  OrderScheduling
//
//  Created by 中道 on 2025/7/31.
//

import UIKit
import DDAutoUIKit_Private
import SnapKit
import RxSwift
import RxCocoa
import BRPickerView

class VehicleMonitorHistoryController : ZDViewController {
    var code : String?
    let timeline = TimelineView()
    let dateView = DateSwitcherView()
    let realtimeButton = UIButton()
    let disposeBag = DisposeBag()
    var fromDateString : String?
    var toDateString : String?
    var alarmResponse : ResponseModel<GetAlarmByCodeDataModel>?
    var refreshSub = ReplaySubject<String?>.create(bufferSize: 1)
    var replaySub = ReplaySubject<ResponseModel<GetAlarmByCodeDataModel>?>.create(bufferSize: 1)
    var videoView = VideoPlayView()
    var closeSub = ReplaySubject<ResponseModel<GetAlarmByCodeDataModel>?>.create(bufferSize: 1)
    init(code: String?) {
        self.code = code
        super.init(nibName: nil, bundle: nil)
    }
    
    @MainActor required public init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        dd_navigationItemTitle = "监控回放"
        dd_navigationBarBackgroundColor = .hex("354683")
        dd_navigationBarTitleTextAttributes = [.foregroundColor : UIColor.white(alpha: 0.7),.font:UIFont.mediumFont(17)]
        dd_navigationBarBarButtonItemAttributes = [.foregroundColor : UIColor.white]

        // 回调当前选中时间
        timeline.onTimeSelected = {[weak self] hour, minute in
            self?.fromDateString = self?.dateView.getDateString()?.appending(" \(hour):\(minute):00")
            if let fromDateString = self?.fromDateString,let dateFormatter = self?.timeline.dateFormatter {
                let toDate = Date(timeIntervalSince1970: ((NSDate.br_date(from: fromDateString, dateFormat: dateFormatter)?.timeIntervalSince1970 ?? 0) + 600))
                self?.toDateString = NSDate.br_string(from: toDate, dateFormat: dateFormatter)

            }else{
                self?.toDateString = self?.fromDateString
            }
            
            if let alarmResponse = self?.alarmResponse {
                self?.replaySub.onNext(alarmResponse)
            }
        }

        realtimeButton.setTitleColor(.white, for: .normal)
        realtimeButton.titleLabel?.font = .dd_systemFont(ofSize: 16, weight: .semibold)
        realtimeButton.backgroundColor = .dd_hex(light: "0273EE", dark: "0273EE")
        realtimeButton.setImage(UIImage(named: "vehicleMonitoring_history_icon"), for: .normal)
        realtimeButton.layer.cornerRadius = 6
        realtimeButton.setTitle("实时监控", for: .normal)
        realtimeButton.dd_customize(with: .ImageLeftPaddingTitleRightWithWholeCenter, padding: 10)
        realtimeButton.rx.tap
            .observe(on: ConcurrentMainScheduler.instance)
            .subscribe(onNext: {[weak self] _ in
                self?.videoView.endShow()
                self?.closeSub.onNext(self?.alarmResponse)
                self?.navigationController?.pushViewController(VehicleMonitorVideoController(vehicleId: self?.alarmResponse?.data?.vehicleId,simNumber: self?.alarmResponse?.data?.imei), animated: true)
            })
            .disposed(by: disposeBag)

        refreshSub
            .observe(on: ConcurrentMainScheduler.instance)
            .do(onNext: {[weak self] response in
                self?.view.dd_showHUD()
            })
            .flatMapLatest { code in
                return RQ.getAlarmByCode(parameters: GetAlarmByCodeParameters(code: code))
                    .flatMap { response in
                        return Single.create { single in
                            if response?.success == true {
                                single(.success(response))
                            }else{
                                single(.failure(CommonError()))
                            }
                            return Disposables.create()
                        }
                    }
            }
            .retry(when: { (rxError: Observable<Error>) -> Observable<Int> in
                return rxError.flatMap({ error in
                    return Observable.timer(RxTimeInterval.seconds(5), scheduler: MainScheduler.asyncInstance)
                })
            })
            .observe(on: ConcurrentMainScheduler.instance)
            .subscribe(onNext: {[weak self] response in
                self?.initUI(response: response)
            })
            .disposed(by: disposeBag)
        
        replaySub
            .observe(on: ConcurrentMainScheduler.instance)
            .do(onNext: {[weak self] response in
                self?.view.dd_showHUD()
            })
            .flatMap({[weak self] response in
                return RQ.getReplayUrl(prameters: GetVideoUrlParameters(vehicleId: response?.data?.vehicleId, simNumber: response?.data?.imei, channel: response?.data?.channel, startDate: self?.fromDateString, endDate: self?.toDateString))
            })
            .observe(on: ConcurrentMainScheduler.instance)
            .do(onNext: {[weak self] response in
                self?.view.dd_hideHUD()
            })
            .observe(on: ConcurrentMainScheduler.instance)
            .subscribe(onNext: {[weak self] response in
                if response?.success == true {
                    if let first = response?.data?.realtimeList?.first {
                        self?.videoView.wsUrl = first
                        if self?.videoView.isPlaying == true {
                            self?.videoView.beginShow()
                        }else{
                        }
                    }
                }else{
                    self?.view.dd_makeToast(response?.msg)
                }
            }).disposed(by: disposeBag)
        
        closeSub
            .flatMapLatest { response in
                return RQ.closeHistoryControl(prameters: GetVideoUrlParameters(simNumber: response?.data?.imei,channel:response?.data?.channel))
            }
            .subscribe(onNext: { response in
            })
            .disposed(by: disposeBag)
        
        
        dateView.prevButton.rx.tap
            .observe(on: ConcurrentMainScheduler.instance)
            .subscribe(onNext: {[weak self] _ in
                if let date = self?.getPreDate(),let dateFormat = self?.dateView.dateFormatter {
                    self?.dateView.setDate(dateString: NSDate.br_string(from: date, dateFormat: dateFormat))
                }
            })
            .disposed(by: disposeBag)
        
        dateView.nextButton.rx.tap
            .observe(on: ConcurrentMainScheduler.instance)
            .subscribe(onNext: {[weak self] _ in
                if let date = self?.getNextDate(),let dateFormat = self?.dateView.dateFormatter {
                    self?.dateView.setDate(dateString: NSDate.br_string(from: date, dateFormat: dateFormat))
                }
            })
            .disposed(by: disposeBag)
        
        dateView.dateButton.rx.tap
            .observe(on: ConcurrentMainScheduler.instance)
            .subscribe(onNext: { _ in
                let picker = BRDatePickerView(pickerMode: .YMD)
                picker.show()
            })
            .disposed(by: disposeBag)
        
        NotificationCenter.default.rx
            .notification(UIApplication.didEnterBackgroundNotification)
            .observe(on: ConcurrentMainScheduler.instance)
            .subscribe(onNext: { [weak self] _ in
                self?.videoView.endShow()
                self?.closeSub.onNext(self?.alarmResponse)
            })
            .disposed(by: disposeBag)
    }
    
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        if timeline.superview == nil {
            view.addSubview(videoView)
            videoView.snp.makeConstraints { make in
                make.top.equalTo(view.snp.top).offset(view.safeAreaInsets.top)
                make.width.equalTo(auto(375))
                make.height.equalTo(auto(300))
                make.centerX.equalToSuperview()
            }
            
            view.addSubview(dateView)
            dateView.snp.makeConstraints { make in
                make.centerX.equalToSuperview()
                make.top.equalTo(videoView.snp.bottom).offset(20)
                make.height.equalTo(64)
                make.width.equalTo(200)
            }

            view.addSubview(timeline)
            timeline.snp.makeConstraints { make in
                make.left.right.equalToSuperview()
                make.height.equalTo(100)
                make.top.equalTo(dateView.snp.bottom).offset(20)
            }
            
            view.addSubview(realtimeButton)
            realtimeButton.snp.makeConstraints { make in
                make.left.right.equalToSuperview().inset(30)
                make.height.equalTo(48)
                make.top.equalTo(timeline.snp.bottom).offset(20)
            }
            
            refreshSub.onNext(code)
        }
    }
    
    func initUI(response: ResponseModel<GetAlarmByCodeDataModel>?) {
        alarmResponse = response
        if let startTime = response?.data?.startTime {
            dateView.setDate(dateString: startTime.components(separatedBy: " ").first)
            let currentDate = (NSDate.br_date(from: startTime, dateFormat: timeline.dateFormatter) as? NSDate) ?? NSDate()
            timeline.scrollToHour(hour: currentDate.br_hour,minute: currentDate.br_minute)
        }
    }
    
    func getPreDate() -> Date? {
        if let dateString = dateView.getDateString() {
            let date = NSDate.br_date(from: dateString, dateFormat: dateView.dateFormatter) as? NSDate
            return date?.br_getNewDate(toDays: -1)
        }
        return Date()
    }
    
    func getNextDate() -> Date? {
        if let dateString = dateView.getDateString(){
            let date = NSDate.br_date(from: dateString, dateFormat: dateView.dateFormatter) as? NSDate
            return date?.br_getNewDate(toDays: 1)
        }
        return Date()
    }
    
    override func dd_backActionPop(_ isAnimated: Bool) {
        super.dd_backActionPop(isAnimated)
        closeSub.onNext(alarmResponse)
    }
}

class DateSwitcherView: UIView {
    let dateFormatter = "yyyy-MM-dd"
    
    // MARK: - UI
    let prevButton: UIButton = {
        let btn = UIButton(type: .system)
        btn.setImage(UIImage(systemName: "chevron.left"), for: .normal)
        btn.tintColor = .darkGray
        return btn
    }()
    
    let nextButton: UIButton = {
        let btn = UIButton(type: .system)
        btn.setImage(UIImage(systemName: "chevron.right"), for: .normal)
        btn.tintColor = .darkGray
        return btn
    }()
    
    let dateButton: UIButton = {
        let btn = UIButton(type: .system)
        btn.titleLabel?.font = .boldSystemFont(ofSize: 18)
        btn.setTitleColor(.black, for: .normal)
        btn.titleLabel?.textAlignment = .center
        btn.backgroundColor = .clear
        return btn
    }()
    
    // MARK: - Init
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupUI()
    }
    
    private func setupUI() {
        
        addSubview(prevButton)
        addSubview(dateButton)
        addSubview(nextButton)
        
        prevButton.snp.makeConstraints { make in
            make.left.equalToSuperview().offset(18)
            make.centerY.equalToSuperview()
            make.width.height.equalTo(28)
        }
        
        nextButton.snp.makeConstraints { make in
            make.right.equalToSuperview().inset(18)
            make.centerY.equalToSuperview()
            make.width.height.equalTo(28)
        }
        
        dateButton.snp.makeConstraints { make in
            make.center.equalToSuperview()
        }
    }
    
    func setDate(dateString: String?) {
        dateButton.setTitle(dateString, for: .normal)
    }
    
    func getDateString() -> String? {
        return dateButton.titleLabel?.text
    }
    
}

class TimelineView: UIView, UIScrollViewDelegate {
    var dateFormatter = "yyyy-MM-dd HH:mm:ss"
    var onTimeSelected: ((String, String) -> Void)?
    var selectHour : Int = 0
    var selectMinute : Int = 0
    private let scrollView = UIScrollView()
    private let contentView = UIView()
    private let indicatorView = UIView()
    private let quarterWidth: CGFloat = 36   // 每15分钟宽度（1小时=4*36=144）
    private let longTickHeight: CGFloat = 10 // 整点、半点高度
    private let shortTickHeight: CGFloat = 5 // 15/45分高度
    private let labelHeight: CGFloat = 18
    private let totalHours = 24

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupUI()
    }
    
    private func setupUI() {
        addSubview(scrollView)
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.delegate = self
        scrollView.snp.makeConstraints { $0.edges.equalToSuperview() }
        scrollView.addSubview(contentView)
        
        indicatorView.backgroundColor = .gray
        addSubview(indicatorView)
        indicatorView.snp.makeConstraints {
            $0.centerX.equalToSuperview()
            $0.width.equalTo(2)
            $0.top.bottom.equalToSuperview()
        }
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        let contentWidth = CGFloat(totalHours) * 4 * quarterWidth
        contentView.frame = CGRect(x: 0, y: 0, width: contentWidth, height: bounds.height)
        scrollView.contentSize = contentView.bounds.size
        let inset = bounds.width / 2
        scrollView.contentInset = UIEdgeInsets(top: 0, left: inset, bottom: 0, right: inset)
        layoutTicks()
    }
    
    private func layoutTicks() {
        contentView.subviews.forEach { $0.removeFromSuperview() }
        for hour in 0..<totalHours {
            for quarter in 0..<4 {
                let minute = quarter * 15
                let x = CGFloat(hour) * 4 * quarterWidth + CGFloat(quarter) * quarterWidth
                let isMajorTick = (minute == 0 || minute == 30)
                let tick = UIView()
                tick.backgroundColor = .gray
                contentView.addSubview(tick)
                tick.snp.makeConstraints {
                    $0.left.equalTo(x)
                    $0.width.equalTo(1)
                    $0.top.equalToSuperview()
                    $0.height.equalTo(isMajorTick ? longTickHeight : shortTickHeight)
                }
                if minute == 0 || minute == 30 {
                    let label = UILabel()
                    label.font = UIFont.systemFont(ofSize: 12)
                    label.textColor = .darkGray
                    // 显示 xx:00 或 xx:30
                    label.text = String(format: "%02d:%02d", hour, minute)
                    label.textAlignment = .center
                    contentView.addSubview(label)
                    label.snp.makeConstraints {
                        $0.centerX.equalTo(tick)
                        $0.top.equalTo(tick.snp.bottom).offset(2)
                        $0.height.equalTo(labelHeight)
                        $0.width.equalTo(44)
                    }
                }
            }
        }
        // 画末尾 24:00 的长刻度线
        let x = CGFloat(totalHours) * 4 * quarterWidth
        let tick = UIView()
        tick.backgroundColor = .gray
        contentView.addSubview(tick)
        tick.snp.makeConstraints {
            $0.left.equalTo(x)
            $0.width.equalTo(1)
            $0.top.equalToSuperview()
            $0.height.equalTo(longTickHeight)
        }
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 12)
        label.textColor = .darkGray
        label.text = "24:00"
        label.textAlignment = .center
        contentView.addSubview(label)
        label.snp.makeConstraints {
            $0.centerX.equalTo(tick)
            $0.top.equalTo(tick.snp.bottom).offset(2)
            $0.height.equalTo(labelHeight)
            $0.width.equalTo(44)
        }
    }
    
    // MARK: - 选中时间（分钟级）
    // 这个在用户停止拖拽时调用
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        fireTimeSelectedCallback(scrollView)
    }

    // 这个在程序性滚动结束（比如setContentOffset动画）时调用
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        fireTimeSelectedCallback(scrollView)
    }

    // 这个在用户用力一甩但还没松手时调用（可选）
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        if !decelerate {
            fireTimeSelectedCallback(scrollView)
        }
    }

    // 封装一个实际的回调方法
    private func fireTimeSelectedCallback(_ scrollView: UIScrollView) {
        let centerX = scrollView.contentOffset.x + bounds.width / 2
        let totalTimelineWidth = CGFloat(totalHours) * 4 * quarterWidth
        let totalMinutes = CGFloat(totalHours * 60)
        let minutePerPt = totalMinutes / totalTimelineWidth
        let selectedMinute = Int((centerX * minutePerPt).rounded())
        let hour = min(max(selectedMinute / 60, 0), totalHours)
        let minute = min(max(selectedMinute % 60, 0), 59)
        let hourString = (hour < 10) ? ("0"+"\(hour)") : "\(hour)"
        let minString = (minute < 10) ? ("0"+"\(minute)") : "\(minute)"
        selectHour = hour
        self.selectMinute = minute
        onTimeSelected?(hourString, minString)
    }

    func scrollToHour(hour: Int, minute: Int = 0, animated: Bool = true) {
        // 计算偏移，分钟级
        let totalMinutes = hour * 60 + minute
        let quarter = CGFloat(totalMinutes) / 15.0
        let offset = quarter * quarterWidth - bounds.width / 2
        scrollView.setContentOffset(CGPoint(x: offset, y: 0), animated: animated)
    }
}
