//
//  MusicEmptyView.swift
//  PhysicalWallPaper
//
//  Created by nkl on 2024/11/13.
//

import Combine
import Foundation
import TSVideoKit
import UIKit

class SongDownloadCell: UITableViewCell {
    lazy var bgView: UIView = .simpleView(color: .clear)

    lazy var bgImageView: UIImageView = .simpleImage(imageName: "ic_minibar_bg")

    lazy var iconView: UIImageView = {
        let img: UIImageView = .init()
        img.customCornerRadius = 12
        img.contentMode = .scaleAspectFill
        return img
    }()

    lazy var titleLabel: UILabel = .simpleLabel(font: .boldSystemFont14, color: .white)

    lazy var timeLabel: UILabel = .simpleLabel(text: "UnKnown".localized(), color: .white.withAlphaComponent(0.4))
    lazy var stackView: UIStackView = {
        let stack: UIStackView = .vStack
        stack.spacing = 8
        return stack
    }()

    lazy var lineView: UIView = .simpleView(color: .white.withAlphaComponent(0.1))

    lazy var downloadBtn: DownloadButton = .init()

    private var cancellable: [AnyCancellable] = []
    private var viewModel: SongDownloadCellViewModel?

    var downloadStateChangeBlock: (DownloadButtonState) -> Void = { _ in }

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        backgroundColor = .clear
        selectionStyle = .none
        addChildren()
        makeConstraints()
    }

    func bindViewModel(viewModel: SongDownloadCellViewModel, isOnline: Bool) {
        // 清理上次的 cancellables
        cancellable.forEach { $0.cancel() }
        cancellable.removeAll()

        self.viewModel = viewModel

        /// 绑定数据
        var videoId: String = ""
        if let model = viewModel.dataModel {
            bindData(video: model)
            videoId = model.videoId
        }
        if let video = viewModel.dataVideo {
            bindVideo(video: video)
            videoId = video.videoId ?? ""
        }

        /// 查找下载器
        if let mDownloader = TSNewDownloadManager.shared.fetchDownloader(identifier: videoId) {
            self.viewModel?.downloader = mDownloader
        } else {
            self.viewModel?.downloader = nil
        }

        /// 添加监听
        self.viewModel?.$downloader
            .compactMap { $0 }
            .flatMap { $0.$progress }
            .receive(on: DispatchQueue.main)
            .sink { [weak self] progress in
                self?.downloadBtn.progressView.set(progress: Double(progress))
            }
            .store(in: &cancellable)

        self.viewModel?.downloader?.$downloadState
            .receive(on: DispatchQueue.main)
            .sink { [weak self] status in
                self?.setDownloadButtonStates(status: status)
            }
            .store(in: &cancellable)

        self.viewModel?.$state.receive(on: DispatchQueue.main).sink(receiveValue: { [weak self] state in
            self?.downloadBtn.downloadState = state
        }).store(in: &cancellable)
    }

    private func bindData(video: VideoOnlineModel) {
        // 数据库找到数据，直接调video绑定
        if let mVideo = TSVideoOperator.shared.dataManager.fetchVideo(videoId: video.videoId) {
            bindVideo(video: mVideo)
        } else {
            titleLabel.text = video.title
            timeLabel.text = video.channelName
            iconView.kf.setImage(with: video.iconUrl, placeholder: UIImage(named: "ic_default"))
            // todo.kailen
            bgImageView.isHidden = PlayerManager.shared.currentVideo?.videoId != video.videoId
            setDownloadButtonStates(status: .idle)
        }
    }

    private func bindVideo(video: TSVideo) {
        titleLabel.text = video.title ?? "--"
        if let artist = video.artist {
            timeLabel.text = artist.isEmpty == true ? "UnKnown".localized() : artist
        } else {
            timeLabel.text = "UnKnown".localized()
        }

        iconView.kf.setImage(with: video.iconUrl, placeholder: UIImage(named: "ic_default"))
        bgImageView.isHidden = PlayerManager.shared.currentVideo?.videoId != video.videoId
        downloadBtn.progressView.set(progress: Double(video.progress))
        setDownloadButtonStates(status: video.videoStatus.asChunkDownloadStatus)
    }

    func setDownloadButtonStates(status: ChunkDownloadStatus) {
        switch status {
        case .idle, .cancel:
            viewModel?.state = .idle(isAnimate: false)
            downloadBtn.adTag.isHidden = PurchaseManager.default.isVip
        case .prasing:
            viewModel?.state = .loading
            downloadBtn.adTag.isHidden = true
        case .praseSuccess:
            break
        case .downloading:
            viewModel?.state = .downloading
            downloadBtn.adTag.isHidden = true
        case .pause:
            viewModel?.state = .pause
            downloadBtn.adTag.isHidden = true
        case .failed:
            viewModel?.state = .retry
            downloadBtn.adTag.isHidden = true
        case .finished:
            viewModel?.state = .done
            downloadBtn.adTag.isHidden = true
        }
    }

    func setDefaultProgress() {
        downloadBtn.downloadState = .idle(isAnimate: false)
        downloadBtn.progressView.set(progress: 0)
    }

    func addChildren() {
        contentView.addSubview(bgView)
        bgView.addSubview(bgImageView)
        bgView.addSubview(iconView)
        stackView.addArrangedSubview(titleLabel)
        let space = UIView()
        stackView.addArrangedSubview(space)
        stackView.addArrangedSubview(timeLabel)
        bgView.addSubview(stackView)
        downloadBtn.adTag.isHidden = PurchaseManager.default.isVip
        bgView.addSubview(downloadBtn)
        downloadBtn.addTarget(self, action: #selector(downloadAction(sender:)), for: .touchUpInside)
        bgView.addSubview(lineView)
    }

    @objc func downloadAction(sender: DownloadButton) {
        switch sender.downloadState {
        case .loading:
            return
        default:
            if let viewModel = viewModel {
                downloadStateChangeBlock(viewModel.state)
            }
        }
    }

    func makeConstraints() {
        bgView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.verticalEdges.equalToSuperview().inset(8)
        }

        bgImageView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }

        iconView.snp.makeConstraints { make in
            make.verticalEdges.equalToSuperview().inset(10)
            make.leading.equalToSuperview().offset(16)
            make.width.height.equalTo(56)
        }
        stackView.snp.makeConstraints { make in
            make.leading.equalTo(iconView.snp.trailing).offset(16)
            make.centerY.equalToSuperview()
            make.trailing.equalTo(downloadBtn.snp.leading).offset(-12)
        }

        downloadBtn.snp.makeConstraints { make in
            make.trailing.equalToSuperview()
            make.centerY.equalToSuperview()
            make.width.height.equalTo(64)
        }

        lineView.snp.makeConstraints { make in
            make.bottom.equalToSuperview()
            make.horizontalEdges.equalToSuperview().inset(16)
            make.height.equalTo(1)
        }
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        cancellable.forEach { $0.cancel() }
        cancellable.removeAll()
        setDefaultProgress()
    }

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

extension TSVideoStatus {
    var asChunkDownloadStatus: ChunkDownloadStatus {
        switch self {
        case .idle:
            return .idle
        case .running:
            return .downloading
        case .cached:
            return .finished
        case .pause:
            return .pause
        case .failed:
            return .failed
        }
    }
}
