//
//  LiveAlbumViewControllers.swift
//  suixinkan
//

import Kingfisher
import PhotosUI
import SnapKit
import UIKit

/// 直播相册列表页，对齐 Android `AliveAlbumScreen`。
final class LiveAlbumListViewController: BaseViewController, UITableViewDelegate {
    private enum Section {
        case main
    }

    private let viewModel = LiveAlbumListViewModel()
    private let liveAPI: any LiveServing
    private let filterCard = UIView()
    private let startButton = UIButton(type: .system)
    private let endButton = UIButton(type: .system)
    private let tableView = UITableView(frame: .zero, style: .plain)
    private let refreshControl = UIRefreshControl()
    private let emptyLabel = UILabel()
    private let loadingIndicator = UIActivityIndicatorView(style: .medium)
    private let bottomBar = UIView()
    private let uploadButton = AppButton(title: "上传素材")
    private var dataSource: UITableViewDiffableDataSource<Section, LiveAlbumFolder>!

    /// 初始化直播相册列表页。
    @MainActor
    init(liveAPI: (any LiveServing)? = nil) {
        self.liveAPI = liveAPI ?? NetworkServices.shared.liveAPI
        super.init(nibName: nil, bundle: nil)
    }

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

    override func setupNavigationBar() {
        title = "直播相册"
    }

    override func setupUI() {
        view.backgroundColor = AppColor.pageBackground
        filterCard.backgroundColor = .white
        filterCard.layer.cornerRadius = 12
        configureDateButton(startButton, title: "开始时间")
        configureDateButton(endButton, title: "结束时间")
        tableView.backgroundColor = .clear
        tableView.separatorStyle = .none
        tableView.delegate = self
        tableView.refreshControl = refreshControl
        tableView.register(LiveAlbumFolderCell.self, forCellReuseIdentifier: LiveAlbumFolderCell.reuseIdentifier)
        tableView.contentInset = UIEdgeInsets(top: 12, left: 0, bottom: 12, right: 0)
        dataSource = UITableViewDiffableDataSource<Section, LiveAlbumFolder>(tableView: tableView) { [weak self] tableView, indexPath, folder in
            guard let cell = tableView.dequeueReusableCell(withIdentifier: LiveAlbumFolderCell.reuseIdentifier, for: indexPath) as? LiveAlbumFolderCell else {
                return UITableViewCell()
            }
            cell.apply(folder)
            cell.onDelete = { [weak self] in self?.confirmDelete(folder) }
            cell.onImageSelected = { [weak self] index in
                self?.navigationController?.pushViewController(
                    LiveAlbumPreviewViewController(folderId: folder.id, startIndex: index),
                    animated: true
                )
            }
            return cell
        }
        emptyLabel.text = "暂无素材"
        emptyLabel.font = .systemFont(ofSize: 14)
        emptyLabel.textColor = UIColor(hex: 0x4B5563)
        emptyLabel.isHidden = true
        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.color = AppColor.primary
        bottomBar.backgroundColor = .white

        view.addSubview(filterCard)
        filterCard.addSubview(startButton)
        filterCard.addSubview(endButton)
        view.addSubview(tableView)
        view.addSubview(emptyLabel)
        view.addSubview(loadingIndicator)
        view.addSubview(bottomBar)
        bottomBar.addSubview(uploadButton)
    }

    override func setupConstraints() {
        filterCard.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide)
            make.leading.trailing.equalToSuperview()
            make.height.equalTo(59)
        }
        startButton.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(12)
            make.centerY.equalToSuperview()
            make.height.equalTo(35)
        }
        endButton.snp.makeConstraints { make in
            make.leading.equalTo(startButton.snp.trailing).offset(8)
            make.trailing.equalToSuperview().inset(12)
            make.centerY.width.height.equalTo(startButton)
        }
        bottomBar.snp.makeConstraints { make in
            make.leading.trailing.bottom.equalToSuperview()
        }
        uploadButton.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(16)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(48)
            make.bottom.equalTo(view.safeAreaLayoutGuide).inset(16)
        }
        tableView.snp.makeConstraints { make in
            make.top.equalTo(filterCard.snp.bottom)
            make.leading.trailing.equalToSuperview()
            make.bottom.equalTo(bottomBar.snp.top)
        }
        emptyLabel.snp.makeConstraints { make in
            make.center.equalTo(tableView)
        }
        loadingIndicator.snp.makeConstraints { make in
            make.center.equalTo(tableView)
        }
    }

    override func bindActions() {
        viewModel.onStateChange = { [weak self] in
            Task { @MainActor in self?.applyViewModel() }
        }
        viewModel.onShowMessage = { [weak self] message in
            Task { @MainActor in self?.showToast(message) }
        }
        refreshControl.addTarget(self, action: #selector(refreshTriggered), for: .valueChanged)
        startButton.addTarget(self, action: #selector(selectStartDate), for: .touchUpInside)
        endButton.addTarget(self, action: #selector(selectEndDate), for: .touchUpInside)
        uploadButton.addTarget(self, action: #selector(openUpload), for: .touchUpInside)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        Task { await viewModel.loadInitial(api: liveAPI) }
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        Task { await viewModel.refresh(api: liveAPI) }
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        guard let last = tableView.indexPathsForVisibleRows?.map(\.row).max() else { return }
        Task { await viewModel.loadMoreIfNeeded(lastVisibleIndex: last, api: liveAPI) }
    }

    @objc private func refreshTriggered() {
        Task { await viewModel.refresh(api: liveAPI) }
    }

    @objc private func selectStartDate() {
        presentDatePicker(initialDate: viewModel.startDate ?? Date()) { [weak self] date in
            guard let self else { return }
            Task { await self.viewModel.setStartDate(date, api: self.liveAPI) }
        }
    }

    @objc private func selectEndDate() {
        presentDatePicker(initialDate: viewModel.endDate ?? Date()) { [weak self] date in
            guard let self else { return }
            Task { await self.viewModel.setEndDate(date, api: self.liveAPI) }
        }
    }

    @objc private func openUpload() {
        navigationController?.pushViewController(LiveAlbumAddViewController(), animated: true)
    }

    private func applyViewModel() {
        let startText = LiveUIFormatter.date(viewModel.startDate)
        let endText = LiveUIFormatter.date(viewModel.endDate)
        setDateButtonTitle(startButton, text: startText.isEmpty ? "开始时间" : startText)
        setDateButtonTitle(endButton, text: endText.isEmpty ? "结束时间" : endText)
        if viewModel.isRefreshing {
            if !refreshControl.isRefreshing { refreshControl.beginRefreshing() }
        } else {
            refreshControl.endRefreshing()
        }
        viewModel.isLoading && viewModel.folders.isEmpty ? loadingIndicator.startAnimating() : loadingIndicator.stopAnimating()
        emptyLabel.isHidden = viewModel.isLoading || !viewModel.folders.isEmpty
        var snapshot = NSDiffableDataSourceSnapshot<Section, LiveAlbumFolder>()
        snapshot.appendSections([.main])
        snapshot.appendItems(viewModel.folders)
        dataSource.apply(snapshot, animatingDifferences: true)
    }

    private func confirmDelete(_ folder: LiveAlbumFolder) {
        showAlert(title: "确认删除", message: "是否确认删除该相册？删除后将无法恢复。") { [weak self] in
            guard let self else { return }
            Task { await self.viewModel.deleteFolder(folder, api: self.liveAPI) }
        }
    }

    private func configureDateButton(_ button: UIButton, title: String) {
        button.backgroundColor = UIColor(hex: 0xF9FAFB)
        button.layer.cornerRadius = 4
        button.setTitleColor(AppColor.textPrimary, for: .normal)
        button.titleLabel?.font = .systemFont(ofSize: 13)
        button.setImage(UIImage(systemName: "calendar"), for: .normal)
        button.tintColor = AppColor.textPrimary
        button.setConfigurationImagePlacement(.leading, padding: 4)
        setDateButtonTitle(button, text: title)
    }

    private func setDateButtonTitle(_ button: UIButton, text: String) {
        button.setTitle(text, for: .normal)
    }

    private func presentDatePicker(initialDate: Date, onConfirm: @escaping (Date) -> Void) {
        let alert = UIAlertController(title: nil, message: "\n\n\n\n\n\n\n\n", preferredStyle: .actionSheet)
        let picker = UIDatePicker()
        picker.datePickerMode = .date
        picker.preferredDatePickerStyle = .wheels
        picker.locale = Locale(identifier: "zh_CN")
        picker.date = initialDate
        alert.view.addSubview(picker)
        picker.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(8)
            make.leading.trailing.equalToSuperview().inset(8)
            make.height.equalTo(216)
        }
        alert.addAction(UIAlertAction(title: "取消", style: .cancel))
        alert.addAction(UIAlertAction(title: "确定", style: .default) { _ in onConfirm(picker.date) })
        present(alert, animated: true)
    }
}

/// 直播相册文件夹 Cell，对齐 Android `AliveAlbumFolderView`。
private final class LiveAlbumFolderCell: UITableViewCell {
    static let reuseIdentifier = "LiveAlbumFolderCell"

    var onDelete: (() -> Void)?
    var onImageSelected: ((Int) -> Void)?

    private let container = UIView()
    private let titleLabel = UILabel()
    private let deleteButton = UIButton(type: .system)
    private let gridStack = UIStackView()
    private var imageViews: [LiveCoverImageView] = []

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

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

    override func prepareForReuse() {
        super.prepareForReuse()
        onDelete = nil
        onImageSelected = nil
        imageViews.forEach { $0.removeFromSuperview() }
        imageViews.removeAll()
        gridStack.arrangedSubviews.forEach { $0.removeFromSuperview() }
    }

    /// 应用直播相册文件夹。
    func apply(_ folder: LiveAlbumFolder) {
        titleLabel.text = folder.displayName
        buildGrid(items: folder.items)
    }

    private func setup() {
        selectionStyle = .none
        backgroundColor = .clear
        container.backgroundColor = .white
        titleLabel.font = .systemFont(ofSize: 16, weight: .medium)
        titleLabel.textColor = AppColor.textPrimary
        deleteButton.setImage(UIImage(systemName: "trash"), for: .normal)
        deleteButton.tintColor = AppColor.danger
        gridStack.axis = .vertical
        gridStack.spacing = 12

        contentView.addSubview(container)
        container.addSubview(titleLabel)
        container.addSubview(deleteButton)
        container.addSubview(gridStack)
        container.snp.makeConstraints { make in
            make.top.bottom.equalToSuperview()
            make.leading.trailing.equalToSuperview()
        }
        titleLabel.snp.makeConstraints { make in
            make.top.leading.equalToSuperview().offset(16)
            make.trailing.lessThanOrEqualTo(deleteButton.snp.leading).offset(-8)
        }
        deleteButton.snp.makeConstraints { make in
            make.top.trailing.equalToSuperview().inset(8)
            make.size.equalTo(44)
        }
        gridStack.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(12)
            make.leading.trailing.equalToSuperview().inset(12)
            make.bottom.equalToSuperview().inset(12)
        }
        deleteButton.addTarget(self, action: #selector(deleteTapped), for: .touchUpInside)
    }

    private func buildGrid(items: [LiveAlbumFile]) {
        let rows = stride(from: 0, to: items.count, by: 2).map { start in
            Array(items[start ..< min(start + 2, items.count)])
        }
        for (rowIndex, rowItems) in rows.enumerated() {
            let rowStack = UIStackView()
            rowStack.axis = .horizontal
            rowStack.spacing = 12
            rowStack.distribution = .fillEqually
            gridStack.addArrangedSubview(rowStack)
            for (columnIndex, item) in rowItems.enumerated() {
                let imageView = LiveCoverImageView(cornerRadius: 12)
                imageView.setURL(item.url)
                imageView.isUserInteractionEnabled = true
                imageView.tag = rowIndex * 2 + columnIndex
                imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(imageTapped(_:))))
                rowStack.addArrangedSubview(imageView)
                imageViews.append(imageView)
                imageView.snp.makeConstraints { make in
                    make.height.equalTo(imageView.snp.width).multipliedBy(9.0 / 16.0)
                }
            }
            if rowItems.count == 1 {
                rowStack.addArrangedSubview(UIView())
            }
        }
    }

    @objc private func deleteTapped() {
        onDelete?()
    }

    @objc private func imageTapped(_ recognizer: UITapGestureRecognizer) {
        guard let view = recognizer.view else { return }
        onImageSelected?(view.tag)
    }
}

/// 上传直播相册素材页，对齐 Android `AliveAlbumAddScreen`。
final class LiveAlbumAddViewController: BaseViewController, PHPickerViewControllerDelegate {
    private let viewModel = LiveAlbumAddViewModel()
    private let liveAPI: any LiveServing
    private let uploader: any LiveOSSUploading
    private let scrollView = UIScrollView()
    private let cardView = UIView()
    private let stackView = UIStackView()
    private let titleField = UITextField()
    private let uploadView = LiveDashedUploadView(title: "点击上传图片", subtitle: "支持 jpg、png、mp4 格式")
    private let filesStack = UIStackView()
    private let bottomBar = UIView()
    private let confirmButton = AppButton(title: "确认")

    /// 初始化上传直播相册素材页。
    @MainActor
    init(
        liveAPI: (any LiveServing)? = nil,
        uploader: (any LiveOSSUploading)? = nil
    ) {
        self.liveAPI = liveAPI ?? NetworkServices.shared.liveAPI
        self.uploader = uploader ?? NetworkServices.shared.ossUploadService
        super.init(nibName: nil, bundle: nil)
    }

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

    override func setupNavigationBar() {
        title = "上传素材"
    }

    override func setupUI() {
        view.backgroundColor = AppColor.pageBackground
        cardView.backgroundColor = .white
        cardView.layer.cornerRadius = 12
        stackView.axis = .vertical
        stackView.spacing = 8
        filesStack.axis = .vertical
        filesStack.spacing = 12
        titleField.placeholder = "请输入作品名称"
        titleField.font = .systemFont(ofSize: 14)
        titleField.layer.borderWidth = 1
        titleField.layer.borderColor = AppColor.border.cgColor
        titleField.layer.cornerRadius = 8
        titleField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 12, height: 1))
        titleField.leftViewMode = .always
        bottomBar.backgroundColor = .white

        view.addSubview(scrollView)
        scrollView.addSubview(cardView)
        cardView.addSubview(stackView)
        addRequiredTitle("直播标题", to: stackView)
        stackView.addArrangedSubview(titleField)
        addRequiredTitle("封面图片", suffix: "（单次最多可上传 20 张图片）", to: stackView)
        stackView.addArrangedSubview(uploadView)
        stackView.addArrangedSubview(filesStack)
        view.addSubview(bottomBar)
        bottomBar.addSubview(confirmButton)
    }

    override func setupConstraints() {
        bottomBar.snp.makeConstraints { make in
            make.leading.trailing.bottom.equalToSuperview()
        }
        confirmButton.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(16)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(48)
            make.bottom.equalTo(view.safeAreaLayoutGuide).inset(16)
        }
        scrollView.snp.makeConstraints { make in
            make.top.leading.trailing.equalTo(view.safeAreaLayoutGuide)
            make.bottom.equalTo(bottomBar.snp.top)
        }
        cardView.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(16)
            make.width.equalTo(scrollView).offset(-32)
        }
        stackView.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(16)
        }
        titleField.snp.makeConstraints { make in
            make.height.equalTo(44)
        }
        uploadView.snp.makeConstraints { make in
            make.height.equalTo(120)
        }
    }

    override func bindActions() {
        viewModel.onStateChange = { [weak self] in
            Task { @MainActor in self?.applyViewModel() }
        }
        viewModel.onShowMessage = { [weak self] message in
            Task { @MainActor in self?.showToast(message) }
        }
        viewModel.onCreateSuccess = { [weak self] in
            Task { @MainActor in self?.navigationController?.popViewController(animated: true) }
        }
        titleField.addTarget(self, action: #selector(titleChanged), for: .editingChanged)
        uploadView.addTarget(self, action: #selector(pickImage), for: .touchUpInside)
        confirmButton.addTarget(self, action: #selector(confirmTapped), for: .touchUpInside)
    }

    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        picker.dismiss(animated: true)
        guard let result = results.first else { return }
        Task {
            do {
                let media = try await LivePhotoPickerLoader.loadImage(from: result)
                await viewModel.addLocalMedia(media, uploader: uploader)
            } catch {
                showToast(error.localizedDescription)
            }
        }
    }

    @objc private func titleChanged() {
        viewModel.updateTitle(titleField.text ?? "")
        if titleField.text != viewModel.title {
            titleField.text = viewModel.title
        }
    }

    @objc private func pickImage() {
        var configuration = PHPickerConfiguration(photoLibrary: .shared())
        configuration.filter = .images
        configuration.selectionLimit = 1
        let picker = PHPickerViewController(configuration: configuration)
        picker.delegate = self
        present(picker, animated: true)
    }

    @objc private func confirmTapped() {
        Task { await viewModel.create(api: liveAPI) }
    }

    private func applyViewModel() {
        viewModel.isLoading ? showLoading() : hideLoading()
        filesStack.arrangedSubviews.forEach { $0.removeFromSuperview() }
        for (index, file) in viewModel.files.enumerated() {
            let view = LiveAlbumUploadedFileView(file: file)
            view.onDelete = { [weak self] in self?.confirmDeleteLocalFile(at: index) }
            filesStack.addArrangedSubview(view)
            view.snp.makeConstraints { make in
                make.height.equalTo(view.snp.width).multipliedBy(9.0 / 16.0)
            }
        }
    }

    private func confirmDeleteLocalFile(at index: Int) {
        showAlert(title: "确认删除", message: "是否确认删除该相册？删除后将无法恢复。") { [weak self] in
            self?.viewModel.deleteLocalFile(at: index)
        }
    }

    private func addRequiredTitle(_ title: String, suffix: String? = nil, to stack: UIStackView) {
        let label = UILabel()
        let text = NSMutableAttributedString(
            string: "\(title) *",
            attributes: [.font: UIFont.systemFont(ofSize: 14, weight: .medium), .foregroundColor: AppColor.textPrimary]
        )
        text.addAttribute(.foregroundColor, value: UIColor.red, range: NSRange(location: title.count + 1, length: 1))
        if let suffix {
            text.append(NSAttributedString(string: suffix, attributes: [.font: UIFont.systemFont(ofSize: 14), .foregroundColor: AppColor.textPrimary]))
        }
        label.attributedText = text
        stack.addArrangedSubview(label)
    }
}

/// 已上传直播素材预览行。
private final class LiveAlbumUploadedFileView: UIView {
    var onDelete: (() -> Void)?

    private let imageView = LiveCoverImageView()
    private let deleteButton = UIButton(type: .system)

    /// 初始化已上传素材视图。
    init(file: LiveAlbumFile) {
        super.init(frame: .zero)
        imageView.setURL(file.url)
        deleteButton.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal)
        deleteButton.tintColor = .gray
        addSubview(imageView)
        addSubview(deleteButton)
        imageView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        deleteButton.snp.makeConstraints { make in
            make.top.trailing.equalToSuperview().inset(4)
            make.size.equalTo(28)
        }
        deleteButton.addTarget(self, action: #selector(deleteTapped), for: .touchUpInside)
    }

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

    @objc private func deleteTapped() {
        onDelete?()
    }
}

/// 直播相册预览页，对齐 Android `AliveAlbumPreviewScreen`。
final class LiveAlbumPreviewViewController: BaseViewController, UIScrollViewDelegate {
    private let viewModel: LiveAlbumPreviewViewModel
    private let liveAPI: any LiveServing
    private let pagingScrollView = UIScrollView()
    private let pageControl = UIPageControl()
    private let emptyLabel = UILabel()
    private let bottomBar = UIView()
    private let deleteButton = LiveActionButton(title: "删除素材")

    /// 初始化直播相册预览页。
    @MainActor
    init(folderId: Int, startIndex: Int, liveAPI: (any LiveServing)? = nil) {
        viewModel = LiveAlbumPreviewViewModel(folderId: folderId, startIndex: startIndex)
        self.liveAPI = liveAPI ?? NetworkServices.shared.liveAPI
        super.init(nibName: nil, bundle: nil)
    }

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

    override func setupNavigationBar() {
        title = "预览"
        navigationController?.navigationBar.barTintColor = .black
        navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white]
        navigationController?.navigationBar.tintColor = .white
    }

    override func setupUI() {
        view.backgroundColor = .black
        pagingScrollView.isPagingEnabled = true
        pagingScrollView.showsHorizontalScrollIndicator = false
        pagingScrollView.delegate = self
        pageControl.currentPageIndicatorTintColor = .white
        pageControl.pageIndicatorTintColor = UIColor.white.withAlphaComponent(0.4)
        emptyLabel.text = "没有可预览的图片"
        emptyLabel.textColor = .white
        emptyLabel.font = .systemFont(ofSize: 16)
        emptyLabel.textAlignment = .center
        bottomBar.backgroundColor = .black
        deleteButton.buttonStyle = .danger
        view.addSubview(pagingScrollView)
        view.addSubview(pageControl)
        view.addSubview(emptyLabel)
        view.addSubview(bottomBar)
        bottomBar.addSubview(deleteButton)
    }

    override func setupConstraints() {
        bottomBar.snp.makeConstraints { make in
            make.leading.trailing.bottom.equalToSuperview()
        }
        deleteButton.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(16)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(48)
            make.bottom.equalTo(view.safeAreaLayoutGuide).inset(16)
        }
        pagingScrollView.snp.makeConstraints { make in
            make.top.leading.trailing.equalTo(view.safeAreaLayoutGuide)
            make.bottom.equalTo(bottomBar.snp.top)
        }
        pageControl.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.bottom.equalTo(pagingScrollView).inset(8)
        }
        emptyLabel.snp.makeConstraints { make in
            make.center.equalTo(pagingScrollView)
        }
    }

    override func bindActions() {
        viewModel.onStateChange = { [weak self] in
            Task { @MainActor in self?.applyViewModel() }
        }
        viewModel.onShowMessage = { [weak self] message in
            Task { @MainActor in self?.showToast(message) }
        }
        deleteButton.addTarget(self, action: #selector(confirmDelete), for: .touchUpInside)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        Task { await viewModel.load(api: liveAPI) }
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.navigationBar.barTintColor = nil
        navigationController?.navigationBar.titleTextAttributes = nil
        navigationController?.navigationBar.tintColor = nil
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        layoutPages()
    }

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let index = Int(round(scrollView.contentOffset.x / max(scrollView.bounds.width, 1)))
        viewModel.updateCurrentIndex(index)
    }

    private func applyViewModel() {
        viewModel.isLoading && viewModel.files.isEmpty ? showLoading() : hideLoading()
        pageControl.numberOfPages = viewModel.files.count
        pageControl.currentPage = viewModel.currentIndex
        emptyLabel.isHidden = !viewModel.files.isEmpty
        deleteButton.isEnabled = !viewModel.files.isEmpty
        buildPages()
    }

    private func buildPages() {
        pagingScrollView.subviews.forEach { $0.removeFromSuperview() }
        for (index, file) in viewModel.files.enumerated() {
            let imageView = LiveCoverImageView(cornerRadius: 0)
            imageView.contentMode = .scaleAspectFit
            imageView.backgroundColor = .black
            imageView.setURL(file.url)
            imageView.tag = index
            pagingScrollView.addSubview(imageView)
        }
        layoutPages()
    }

    private func layoutPages() {
        let size = pagingScrollView.bounds.size
        guard size.width > 0 else { return }
        for (index, view) in pagingScrollView.subviews.enumerated() {
            view.frame = CGRect(x: CGFloat(index) * size.width, y: 0, width: size.width, height: size.height)
        }
        pagingScrollView.contentSize = CGSize(width: size.width * CGFloat(viewModel.files.count), height: size.height)
        pagingScrollView.setContentOffset(CGPoint(x: CGFloat(viewModel.currentIndex) * size.width, y: 0), animated: false)
    }

    @objc private func confirmDelete() {
        showAlert(title: "确认删除", message: "是否确认删除该素材？删除后将无法恢复。") { [weak self] in
            guard let self else { return }
            Task { await self.viewModel.deleteCurrentFile(api: self.liveAPI) }
        }
    }
}
