//
//  CloudDriveTransferViewController.swift
//  suixinkan
//

import SnapKit
import UIKit

/// 云盘传输管理页，严格对齐 Android `CloudStorageTransitScreen`。
final class CloudDriveTransferViewController: BaseViewController {
    private enum Tab: Int {
        case upload
        case download
    }

    private enum Section {
        case main
    }

    private let manager: CloudTransferManager
    private let navigationDivider = UIView()
    private let tabContainer = UIView()
    private let uploadTabButton = UIButton(type: .system)
    private let downloadTabButton = UIButton(type: .system)
    private let tabIndicator = UIView()
    private let tableView = UITableView(frame: .zero, style: .plain)
    private var dataSource: UITableViewDiffableDataSource<Section, String>!
    private var selectedTab: Tab = .upload
    private var previousStandardAppearance: UINavigationBarAppearance?
    private var previousScrollEdgeAppearance: UINavigationBarAppearance?
    private var previousCompactAppearance: UINavigationBarAppearance?
    private var previousNavigationTintColor: UIColor?

    /// 初始化传输管理页。
    init(manager: CloudTransferManager? = nil) {
        self.manager = manager ?? .shared
        super.init(nibName: nil, bundle: nil)
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func setupNavigationBar() {
        let titleLabel = UILabel()
        titleLabel.text = "传输管理"
        titleLabel.textColor = UIColor(hex: 0x333333)
        titleLabel.font = .systemFont(ofSize: 18)
        navigationItem.titleView = titleLabel

        let backButton = UIButton(type: .system)
        backButton.setImage(
            UIImage(systemName: "chevron.left")?.withConfiguration(UIImage.SymbolConfiguration(pointSize: 20, weight: .medium)),
            for: .normal
        )
        backButton.tintColor = .black
        backButton.accessibilityLabel = "返回"
        backButton.addTarget(self, action: #selector(backTapped), for: .touchUpInside)
        backButton.snp.makeConstraints { make in make.width.height.equalTo(44) }
        navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
    }

    override func setupUI() {
        view.backgroundColor = AppColor.pageBackground
        navigationDivider.backgroundColor = UIColor(hex: 0xEEEEEE)
        tabContainer.backgroundColor = .white
        configureTabButton(uploadTabButton, title: "上传", action: #selector(uploadTabTapped))
        configureTabButton(downloadTabButton, title: "下载", action: #selector(downloadTabTapped))
        tabIndicator.backgroundColor = AppColor.primary

        tableView.backgroundColor = AppColor.pageBackground
        tableView.separatorStyle = .none
        tableView.showsVerticalScrollIndicator = false
        tableView.contentInsetAdjustmentBehavior = .never
        tableView.delegate = self
        tableView.register(CloudTransferCell.self, forCellReuseIdentifier: CloudTransferCell.reuseIdentifier)

        view.addSubview(navigationDivider)
        view.addSubview(tabContainer)
        tabContainer.addSubview(uploadTabButton)
        tabContainer.addSubview(downloadTabButton)
        tabContainer.addSubview(tabIndicator)
        view.addSubview(tableView)

        configureDataSource()
    }

    override func setupConstraints() {
        navigationDivider.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide)
            make.leading.trailing.equalToSuperview()
            make.height.equalTo(0.5)
        }
        tabContainer.snp.makeConstraints { make in
            make.top.equalTo(navigationDivider.snp.bottom)
            make.leading.trailing.equalToSuperview()
            make.height.equalTo(48)
        }
        uploadTabButton.snp.makeConstraints { make in
            make.top.leading.bottom.equalToSuperview()
            make.width.equalToSuperview().multipliedBy(0.5)
        }
        downloadTabButton.snp.makeConstraints { make in
            make.top.trailing.bottom.equalToSuperview()
            make.width.equalTo(uploadTabButton)
        }
        tabIndicator.snp.makeConstraints { make in
            make.bottom.equalToSuperview()
            make.height.equalTo(2)
            make.width.equalToSuperview().multipliedBy(0.5)
            make.leading.equalToSuperview()
        }
        tableView.snp.makeConstraints { make in
            make.top.equalTo(tabContainer.snp.bottom)
            make.leading.trailing.bottom.equalToSuperview()
        }
    }

    override func bindActions() {
        manager.onTasksChange = { [weak self] in
            Task { @MainActor in self?.applySnapshot(animated: true) }
        }
        updateTabs(animated: false)
        applySnapshot(animated: false)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        applyCloudNavigationBarAppearance()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        restoreNavigationBarAppearance()
    }

    private var visibleTasks: [CloudTransferTask] {
        selectedTab == .upload ? manager.uploadTasks : manager.downloadTasks
    }

    private func configureTabButton(_ button: UIButton, title: String, action: Selector) {
        button.setTitle(title, for: .normal)
        button.titleLabel?.font = .systemFont(ofSize: 14)
        button.addTarget(self, action: action, for: .touchUpInside)
    }

    private func applyCloudNavigationBarAppearance() {
        guard let navigationBar = navigationController?.navigationBar else { return }
        previousStandardAppearance = navigationBar.standardAppearance
        previousScrollEdgeAppearance = navigationBar.scrollEdgeAppearance
        previousCompactAppearance = navigationBar.compactAppearance
        previousNavigationTintColor = navigationBar.tintColor
        let appearance = UINavigationBarAppearance()
        appearance.configureWithOpaqueBackground()
        appearance.backgroundColor = .white
        appearance.shadowColor = .clear
        navigationBar.standardAppearance = appearance
        navigationBar.scrollEdgeAppearance = appearance
        navigationBar.compactAppearance = appearance
        navigationBar.tintColor = .black
    }

    private func restoreNavigationBarAppearance() {
        guard let navigationBar = navigationController?.navigationBar else { return }
        if let previousStandardAppearance {
            navigationBar.standardAppearance = previousStandardAppearance
        }
        navigationBar.scrollEdgeAppearance = previousScrollEdgeAppearance
        navigationBar.compactAppearance = previousCompactAppearance
        navigationBar.tintColor = previousNavigationTintColor
    }

    private func configureDataSource() {
        dataSource = UITableViewDiffableDataSource<Section, String>(tableView: tableView) { [weak self] tableView, indexPath, taskID in
            guard let self,
                  let task = self.visibleTasks.first(where: { $0.id == taskID }),
                  let cell = tableView.dequeueReusableCell(
                    withIdentifier: CloudTransferCell.reuseIdentifier,
                    for: indexPath
                  ) as? CloudTransferCell else {
                return UITableViewCell()
            }
            cell.apply(task: task)
            cell.onPrimaryAction = { [weak self] in
                guard let self else { return }
                switch task.kind {
                case .upload:
                    task.status == .uploading ? self.manager.pauseUpload(id: task.id) : self.manager.resumeUpload(id: task.id)
                case .download:
                    task.status == .downloading ? self.manager.pauseDownload(id: task.id) : self.manager.resumeDownload(id: task.id)
                }
            }
            cell.onCancel = { [weak self] in
                guard let self else { return }
                task.kind == .upload ? self.manager.cancelUpload(id: task.id) : self.manager.cancelDownload(id: task.id)
            }
            return cell
        }
        dataSource.defaultRowAnimation = .fade
    }

    private func applySnapshot(animated: Bool) {
        let previousIDs = Set(dataSource.snapshot().itemIdentifiers)
        let taskIDs = visibleTasks.map(\.id)
        var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
        snapshot.appendSections([.main])
        snapshot.appendItems(taskIDs)
        snapshot.reconfigureItems(taskIDs.filter(previousIDs.contains))
        dataSource.apply(snapshot, animatingDifferences: animated)
    }

    private func updateTabs(animated: Bool) {
        let uploadSelected = selectedTab == .upload
        uploadTabButton.setTitleColor(uploadSelected ? AppColor.primary : UIColor(hex: 0x333333), for: .normal)
        downloadTabButton.setTitleColor(uploadSelected ? UIColor(hex: 0x333333) : AppColor.primary, for: .normal)
        uploadTabButton.titleLabel?.font = .systemFont(ofSize: 14, weight: uploadSelected ? .medium : .regular)
        downloadTabButton.titleLabel?.font = .systemFont(ofSize: 14, weight: uploadSelected ? .regular : .medium)
        tabIndicator.snp.updateConstraints { make in
            make.leading.equalToSuperview().offset(uploadSelected ? 0 : view.bounds.width / 2)
        }
        guard animated else {
            tabContainer.layoutIfNeeded()
            return
        }
        UIView.animate(withDuration: 0.2) { self.tabContainer.layoutIfNeeded() }
    }

    private func selectTab(_ tab: Tab) {
        guard selectedTab != tab else { return }
        selectedTab = tab
        updateTabs(animated: true)
        applySnapshot(animated: true)
        tableView.setContentOffset(.zero, animated: false)
    }

    @objc private func backTapped() {
        navigationController?.popViewController(animated: true)
    }

    @objc private func uploadTabTapped() {
        selectTab(.upload)
    }

    @objc private func downloadTabTapped() {
        selectTab(.download)
    }
}

extension CloudDriveTransferViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        119
    }
}

/// 云盘传输任务 Cell，严格对齐 Android 上传/下载任务卡片。
private final class CloudTransferCell: UITableViewCell {
    static let reuseIdentifier = "CloudTransferCell"

    var onPrimaryAction: (() -> Void)?
    var onCancel: (() -> Void)?

    private let cardView = UIView()
    private let iconView = UIImageView()
    private let titleLabel = UILabel()
    private let statusLabel = UILabel()
    private let primaryButton = UIButton(type: .system)
    private let cancelButton = UIButton(type: .system)
    private let progressView = UIProgressView(progressViewStyle: .default)
    private let percentLabel = UILabel()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupUI()
        setupConstraints()
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        onPrimaryAction = nil
        onCancel = nil
    }

    /// 应用传输任务状态。
    func apply(task: CloudTransferTask) {
        iconView.image = CloudDriveAsset.image(
            named: task.fileType == 1 ? "icon_cloud_storage_file_type_video" : "icon_cloud_storage_file_type_photo",
            fallbackSystemName: task.fileType == 1 ? "video.fill" : "photo.fill"
        )
        titleLabel.text = task.fileName
        statusLabel.text = statusText(for: task)
        progressView.progress = Float(task.progress) / 100
        percentLabel.text = "\(task.progress)%"

        let isRunning = task.status == .uploading || task.status == .downloading
        let canResume = task.status == .paused || task.status == .failed
        primaryButton.setImage(
            UIImage(systemName: isRunning ? "pause.fill" : "play.fill")?.withConfiguration(UIImage.SymbolConfiguration(pointSize: 20)),
            for: .normal
        )
        primaryButton.isHidden = !(isRunning || canResume)
    }

    private func statusText(for task: CloudTransferTask) -> String {
        switch task.kind {
        case .upload:
            let status: String
            switch task.status {
            case .uploading: status = "上传中"
            case .paused: status = "已暂停"
            case .failed: status = "失败"
            default: status = ""
            }
            let size = CloudDriveFormatter.fileSize(task.fileSize)
            return status.isEmpty ? size : "\(status) \(size)"
        case .download:
            switch task.status {
            case .downloading: return "下载中"
            case .paused: return "已暂停"
            case .failed: return "失败"
            case .completed: return "已完成"
            default: return ""
            }
        }
    }

    private func setupUI() {
        backgroundColor = .clear
        selectionStyle = .none
        cardView.backgroundColor = .white
        cardView.layer.cornerRadius = 8
        cardView.clipsToBounds = true

        iconView.contentMode = .scaleAspectFit
        titleLabel.font = .systemFont(ofSize: 15)
        titleLabel.textColor = UIColor(hex: 0x333333)
        titleLabel.lineBreakMode = .byTruncatingMiddle
        statusLabel.font = .systemFont(ofSize: 12)
        statusLabel.textColor = .gray
        progressView.progressTintColor = AppColor.primary
        progressView.trackTintColor = UIColor(hex: 0xE5E7EB)
        progressView.transform = CGAffineTransform(scaleX: 1, y: 2)
        percentLabel.font = .systemFont(ofSize: 11)
        percentLabel.textColor = UIColor(hex: 0x4B5563)
        percentLabel.textAlignment = .right

        primaryButton.tintColor = UIColor(hex: 0x333333)
        cancelButton.tintColor = UIColor(hex: 0x333333)
        cancelButton.setImage(
            UIImage(systemName: "xmark")?.withConfiguration(UIImage.SymbolConfiguration(pointSize: 20)),
            for: .normal
        )
        primaryButton.accessibilityLabel = "暂停或继续"
        cancelButton.accessibilityLabel = "取消任务"
        primaryButton.addTarget(self, action: #selector(primaryTapped), for: .touchUpInside)
        cancelButton.addTarget(self, action: #selector(cancelTapped), for: .touchUpInside)

        contentView.addSubview(cardView)
        [iconView, titleLabel, statusLabel, primaryButton, cancelButton, progressView, percentLabel]
            .forEach(cardView.addSubview)
    }

    private func setupConstraints() {
        cardView.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(12)
            make.leading.trailing.equalToSuperview().inset(12)
            make.bottom.equalToSuperview()
        }
        iconView.snp.makeConstraints { make in
            make.leading.top.equalToSuperview().offset(12)
            make.width.height.equalTo(48)
        }
        cancelButton.snp.makeConstraints { make in
            make.trailing.equalToSuperview()
            make.top.equalToSuperview().offset(8)
            make.width.height.equalTo(44)
        }
        primaryButton.snp.makeConstraints { make in
            make.trailing.equalTo(cancelButton.snp.leading)
            make.centerY.equalTo(cancelButton)
            make.width.height.equalTo(44)
        }
        titleLabel.snp.makeConstraints { make in
            make.leading.equalTo(iconView.snp.trailing).offset(12)
            make.top.equalTo(iconView)
            make.trailing.equalTo(primaryButton.snp.leading).offset(-4)
        }
        statusLabel.snp.makeConstraints { make in
            make.leading.trailing.equalTo(titleLabel)
            make.top.equalTo(titleLabel.snp.bottom).offset(4)
        }
        progressView.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(12)
            make.trailing.equalToSuperview().inset(12)
            make.top.equalTo(iconView.snp.bottom).offset(12)
            make.height.equalTo(4)
        }
        percentLabel.snp.makeConstraints { make in
            make.top.equalTo(progressView.snp.bottom).offset(4)
            make.trailing.equalTo(progressView)
            make.bottom.equalToSuperview().inset(12)
        }
    }

    @objc private func primaryTapped() {
        onPrimaryAction?()
    }

    @objc private func cancelTapped() {
        onCancel?()
    }
}
