//
//  TravelAlbumDetailViewController.swift
//  suixinkan
//

import Kingfisher
import SnapKit
import UIKit

/// 相册详情管理页，对齐 Android `TravelAlbumDetailScreen`。
final class TravelAlbumDetailViewController: BaseViewController {
    private let viewModel: TravelAlbumDetailViewModel
    private let api: any TravelAlbumServing

    private let scrollContainer = UIView()
    private let infoCard = TravelAlbumInfoCard()
    private let manageCard = UIView()
    private let tabStack = UIStackView()
    private let allTabButton = UIButton(type: .system)
    private let purchasedTabButton = UIButton(type: .system)
    private let sortButton = UIButton(type: .system)
    private let selectButton = UIButton(type: .system)
    private var collectionView: UICollectionView!
    private var dataSource: UICollectionViewDiffableDataSource<Int, TravelAlbumMaterial>!
    private let bottomBar = UIView()
    private let bottomActionStack = UIStackView()
    private let deleteSelectedButton = UIButton(type: .system)
    private let uploadButton = UIButton(type: .system)
    private var isDeleteSelectedButtonVisible = false

    init(albumId: Int, api: (any TravelAlbumServing)? = nil) {
        viewModel = TravelAlbumDetailViewModel(albumId: albumId)
        self.api = api ?? NetworkServices.shared.travelAlbumAPI
        super.init(nibName: nil, bundle: nil)
    }

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

    override func setupNavigationBar() {
        title = "相册管理"
        navigationItem.rightBarButtonItem = UIBarButtonItem(
            image: UIImage(systemName: "ellipsis"),
            menu: UIMenu(children: [
                UIAction(title: "删除相册", image: UIImage(systemName: "trash"), attributes: .destructive) { [weak self] _ in
                    self?.confirmDeleteAlbum()
                },
            ])
        )
    }

    override func setupUI() {
        view.backgroundColor = AppColor.pageBackground

        manageCard.backgroundColor = .white
        manageCard.layer.cornerRadius = 12
        manageCard.layer.shadowColor = UIColor.black.withAlphaComponent(0.08).cgColor
        manageCard.layer.shadowOpacity = 1
        manageCard.layer.shadowRadius = 6
        manageCard.layer.shadowOffset = CGSize(width: 0, height: 2)

        tabStack.axis = .horizontal
        tabStack.spacing = 8
        configurePillButton(allTabButton)
        configurePillButton(purchasedTabButton)
        configureIconButton(sortButton, image: UIImage(systemName: "line.3.horizontal.decrease.circle.fill"))
        configureIconButton(selectButton, image: UIImage(systemName: "circle"))

        collectionView = UICollectionView(frame: .zero, collectionViewLayout: makeLayout())
        collectionView.backgroundColor = .white
        collectionView.delegate = self
        collectionView.register(TravelAlbumMaterialCell.self, forCellWithReuseIdentifier: TravelAlbumMaterialCell.reuseIdentifier)
        dataSource = UICollectionViewDiffableDataSource<Int, TravelAlbumMaterial>(collectionView: collectionView) {
            [weak self] collectionView, indexPath, material in
            let cell = collectionView.dequeueReusableCell(
                withReuseIdentifier: TravelAlbumMaterialCell.reuseIdentifier,
                for: indexPath
            ) as! TravelAlbumMaterialCell
            cell.apply(
                material: material,
                selectionMode: self?.viewModel.isSelectionMode == true,
                selected: self?.viewModel.selectedMaterialIds.contains(material.id) == true
            )
            return cell
        }

        bottomBar.backgroundColor = AppColor.pageBackground
        bottomActionStack.axis = .vertical
        bottomActionStack.spacing = 8
        configureBottomButton(deleteSelectedButton, title: "删除选中(0)", color: UIColor(hex: 0xE53935))
        configureBottomButton(uploadButton, title: "上传照片", color: AppColor.primary)
        deleteSelectedButton.isHidden = true
        deleteSelectedButton.alpha = 0

        view.addSubview(scrollContainer)
        scrollContainer.addSubview(infoCard)
        scrollContainer.addSubview(manageCard)
        manageCard.addSubview(tabStack)
        tabStack.addArrangedSubview(allTabButton)
        tabStack.addArrangedSubview(purchasedTabButton)
        manageCard.addSubview(sortButton)
        manageCard.addSubview(selectButton)
        manageCard.addSubview(collectionView)
        view.addSubview(bottomBar)
        bottomBar.addSubview(bottomActionStack)
        bottomActionStack.addArrangedSubview(deleteSelectedButton)
        bottomActionStack.addArrangedSubview(uploadButton)
    }

    override func setupConstraints() {
        bottomBar.snp.makeConstraints { make in
            make.leading.trailing.bottom.equalToSuperview()
        }
        bottomActionStack.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(12)
            make.leading.trailing.equalToSuperview().inset(20)
            make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-12)
        }
        deleteSelectedButton.snp.makeConstraints { make in
            make.height.equalTo(48).priority(.high)
        }
        uploadButton.snp.makeConstraints { make in
            make.height.equalTo(48).priority(.high)
        }
        scrollContainer.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide).offset(12)
            make.leading.trailing.equalToSuperview().inset(16)
            make.bottom.equalTo(bottomBar.snp.top).offset(-8)
        }
        infoCard.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview()
            make.height.greaterThanOrEqualTo(76)
        }
        manageCard.snp.makeConstraints { make in
            make.top.equalTo(infoCard.snp.bottom).offset(12)
            make.leading.trailing.bottom.equalToSuperview()
        }
        tabStack.snp.makeConstraints { make in
            make.top.leading.equalToSuperview().offset(12)
            make.height.equalTo(32)
        }
        sortButton.snp.makeConstraints { make in
            make.centerY.equalTo(tabStack)
            make.trailing.equalTo(selectButton.snp.leading).offset(-8)
            make.size.equalTo(32)
        }
        selectButton.snp.makeConstraints { make in
            make.centerY.equalTo(tabStack)
            make.trailing.equalToSuperview().offset(-12)
            make.size.equalTo(32)
        }
        collectionView.snp.makeConstraints { make in
            make.top.equalTo(tabStack.snp.bottom).offset(12)
            make.leading.trailing.bottom.equalToSuperview().inset(12)
        }
    }

    override func bindActions() {
        infoCard.onCall = { [weak self] phone in self?.call(phone) }
        allTabButton.addTarget(self, action: #selector(allTabTapped), for: .touchUpInside)
        purchasedTabButton.addTarget(self, action: #selector(purchasedTabTapped), for: .touchUpInside)
        sortButton.addTarget(self, action: #selector(sortTapped), for: .touchUpInside)
        selectButton.addTarget(self, action: #selector(selectTapped), for: .touchUpInside)
        deleteSelectedButton.addTarget(self, action: #selector(deleteSelectedTapped), for: .touchUpInside)
        uploadButton.addTarget(self, action: #selector(uploadTapped), for: .touchUpInside)
        viewModel.onStateChange = { [weak self] in
            Task { @MainActor in self?.applyViewModel() }
        }
        viewModel.onShowMessage = { [weak self] message in
            Task { @MainActor in self?.showToast(message) }
        }
        viewModel.onDeletedAlbum = { [weak self] _ in
            Task { @MainActor in
                guard let self else { return }
                TravelAlbumOTGPhotoStore().clearAlbum(albumId: self.viewModel.albumId)
                self.navigationController?.popViewController(animated: true)
            }
        }
    }

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

    @MainActor
    private func applyViewModel() {
        if let album = viewModel.album {
            infoCard.apply(album: album)
        }
        configureTabButton(allTabButton, title: "全部照片\(viewModel.allPhotoCount)", selected: viewModel.selectedTab == .all)
        configureTabButton(purchasedTabButton, title: "已购照片", selected: viewModel.selectedTab == .purchased)
        selectButton.isHidden = viewModel.selectedTab != .all
        selectButton.setImage(UIImage(systemName: viewModel.isSelectionMode ? "checkmark.circle.fill" : "circle"), for: .normal)
        selectButton.tintColor = viewModel.isSelectionMode ? AppColor.primary : AppColor.textTertiary
        deleteSelectedButton.setTitle("删除选中(\(viewModel.selectedMaterialIds.count))", for: .normal)
        setDeleteSelectedButtonVisible(viewModel.isSelectionMode && !viewModel.selectedMaterialIds.isEmpty)

        var snapshot = NSDiffableDataSourceSnapshot<Int, TravelAlbumMaterial>()
        snapshot.appendSections([0])
        snapshot.appendItems(viewModel.materials)
        if !snapshot.itemIdentifiers.isEmpty {
            snapshot.reconfigureItems(snapshot.itemIdentifiers)
        }
        dataSource.apply(snapshot, animatingDifferences: true)

        if viewModel.isLoading && viewModel.album == nil {
            showLoading()
        } else {
            hideLoading()
        }
    }

    private func configurePillButton(_ button: UIButton) {
        button.titleLabel?.font = .systemFont(ofSize: 13, weight: .medium)
        button.layer.cornerRadius = 16
        button.setConfigurationContentInsets(
            NSDirectionalEdgeInsets(top: 7, leading: 14, bottom: 7, trailing: 14)
        )
    }

    private func configureTabButton(_ button: UIButton, title: String, selected: Bool) {
        button.setTitle(title, for: .normal)
        button.backgroundColor = selected ? AppColor.primary : UIColor(hex: 0xEAF4FF)
        button.setTitleColor(selected ? .white : AppColor.primary, for: .normal)
    }

    private func configureIconButton(_ button: UIButton, image: UIImage?) {
        button.setImage(image, for: .normal)
        button.backgroundColor = UIColor(hex: 0xEAF4FF)
        button.tintColor = AppColor.primary
        button.layer.cornerRadius = 16
    }

    private func configureBottomButton(_ button: UIButton, title: String, color: UIColor) {
        button.setTitle(title, for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
        button.backgroundColor = color
        button.layer.cornerRadius = 10
    }

    private func setDeleteSelectedButtonVisible(_ visible: Bool) {
        guard visible != isDeleteSelectedButtonVisible else { return }
        isDeleteSelectedButtonVisible = visible

        let changes = {
            self.deleteSelectedButton.isHidden = !visible
            self.deleteSelectedButton.alpha = visible ? 1 : 0
            self.view.layoutIfNeeded()
        }
        guard view.window != nil else {
            changes()
            return
        }

        view.layoutIfNeeded()
        UIView.animate(
            withDuration: 0.25,
            delay: 0,
            options: [.curveEaseInOut, .beginFromCurrentState],
            animations: changes
        )
    }

    private func makeLayout() -> UICollectionViewCompositionalLayout {
        UICollectionViewCompositionalLayout { _, environment in
            let spacing: CGFloat = 8
            let width = (environment.container.effectiveContentSize.width - spacing * 2) / 3
            let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(width), heightDimension: .absolute(width + 38))
            let item = NSCollectionLayoutItem(layoutSize: itemSize)
            let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(width + 38))
            let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, repeatingSubitem: item, count: 3)
            group.interItemSpacing = .fixed(spacing)
            let section = NSCollectionLayoutSection(group: group)
            section.interGroupSpacing = 12
            return section
        }
    }

    private func call(_ phone: String) {
        guard !phone.isEmpty, let url = URL(string: "tel:\(phone)") else { return }
        UIApplication.shared.open(url)
    }

    private func confirmDeleteAlbum() {
        let alert = UIAlertController(title: "删除相册", message: "确定删除该相册吗？已有购买素材的相册无法删除。", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "取消", style: .cancel))
        alert.addAction(UIAlertAction(title: "删除", style: .destructive) { [weak self] _ in
            guard let self else { return }
            Task { await self.viewModel.deleteAlbum(api: self.api) }
        })
        present(alert, animated: true)
    }

    @objc private func allTabTapped() {
        Task { await viewModel.selectTab(.all, api: api) }
    }

    @objc private func purchasedTabTapped() {
        Task { await viewModel.selectTab(.purchased, api: api) }
    }

    @objc private func sortTapped() {
        let alert = UIAlertController(title: "排序", message: nil, preferredStyle: .actionSheet)
        TravelAlbumDetailViewModel.SortOption.allCases.forEach { option in
            alert.addAction(UIAlertAction(title: option.title, style: .default) { [weak self] _ in
                guard let self else { return }
                Task { await self.viewModel.setSortOption(option, api: self.api) }
            })
        }
        alert.addAction(UIAlertAction(title: "取消", style: .cancel))
        present(alert, animated: true)
    }

    @objc private func selectTapped() {
        viewModel.toggleSelectionMode()
    }

    @objc private func deleteSelectedTapped() {
        let count = viewModel.selectedMaterialIds.count
        let alert = UIAlertController(title: "删除素材", message: "确定删除选中的 \(count) 张素材吗？", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "取消", style: .cancel))
        alert.addAction(UIAlertAction(title: "删除", style: .destructive) { [weak self] _ in
            guard let self else { return }
            Task { await self.viewModel.deleteSelectedMaterials(api: self.api) }
        })
        present(alert, animated: true)
    }

    @objc private func uploadTapped() {
        let album = viewModel.album
        let controller = WiredCameraTransferViewController(
            viewModel: WiredCameraTransferViewModel(
                albumId: album?.id ?? viewModel.albumId,
                albumTitle: album?.name ?? "",
                headerPhone: album?.displayPhone ?? ""
            )
        )
        navigationController?.pushViewController(controller, animated: true)
    }
}

extension TravelAlbumDetailViewController: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        guard let material = dataSource.itemIdentifier(for: indexPath) else { return }
        viewModel.toggleMaterialSelection(material)
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let visible = collectionView.indexPathsForVisibleItems.map(\.item).max() ?? 0
        Task { await viewModel.loadMoreIfNeeded(lastVisibleIndex: visible, api: api) }
    }
}

/// 旅拍相册详情信息卡。
private final class TravelAlbumInfoCard: UIView {
    var onCall: ((String) -> Void)?
    private var phone = ""

    private let iconView = UIImageView(image: UIImage(systemName: "checklist"))
    private let phoneLabel = UILabel()
    private let timeLabel = UILabel()
    private let callButton = UIButton(type: .system)

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        layer.cornerRadius = 12
        layer.shadowColor = UIColor.black.withAlphaComponent(0.08).cgColor
        layer.shadowOpacity = 1
        layer.shadowRadius = 6
        layer.shadowOffset = CGSize(width: 0, height: 2)

        let iconBox = UIView()
        iconBox.backgroundColor = AppColor.primary
        iconBox.layer.cornerRadius = 10
        iconView.tintColor = .white
        iconView.contentMode = .scaleAspectFit
        phoneLabel.font = .systemFont(ofSize: 14, weight: .medium)
        phoneLabel.textColor = AppColor.textPrimary
        timeLabel.font = .systemFont(ofSize: 12)
        timeLabel.textColor = AppColor.textTertiary
        callButton.setImage(UIImage(systemName: "phone.fill"), for: .normal)
        callButton.tintColor = AppColor.primary
        callButton.backgroundColor = UIColor(hex: 0xEAF4FF)
        callButton.layer.cornerRadius = 20

        addSubview(iconBox)
        iconBox.addSubview(iconView)
        addSubview(phoneLabel)
        addSubview(timeLabel)
        addSubview(callButton)
        iconBox.snp.makeConstraints { make in
            make.leading.top.bottom.equalToSuperview().inset(14)
            make.size.equalTo(48)
        }
        iconView.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(28)
        }
        phoneLabel.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(16)
            make.leading.equalTo(iconBox.snp.trailing).offset(12)
            make.trailing.equalTo(callButton.snp.leading).offset(-12)
        }
        timeLabel.snp.makeConstraints { make in
            make.top.equalTo(phoneLabel.snp.bottom).offset(6)
            make.leading.trailing.equalTo(phoneLabel)
            make.bottom.equalToSuperview().offset(-16)
        }
        callButton.snp.makeConstraints { make in
            make.trailing.equalToSuperview().offset(-14)
            make.centerY.equalToSuperview()
            make.size.equalTo(40)
        }
        callButton.addTarget(self, action: #selector(callTapped), for: .touchUpInside)
    }

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

    func apply(album: TravelAlbum) {
        phone = album.displayPhone
        phoneLabel.text = "手机号 \(TravelAlbumDisplayFormatter.maskPhone(album.displayPhone))"
        timeLabel.text = "创建时间 \(album.createdAt)"
    }

    @objc private func callTapped() {
        onCall?(phone)
    }
}

/// 旅拍相册素材网格 cell。
private final class TravelAlbumMaterialCell: UICollectionViewCell {
    static let reuseIdentifier = "TravelAlbumMaterialCell"

    private let imageView = UIImageView()
    private let statusLabel = UILabel()
    private let checkImageView = UIImageView()
    private let nameLabel = UILabel()
    private let sizeLabel = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        imageView.layer.cornerRadius = 8
        statusLabel.text = "已上传"
        statusLabel.font = .systemFont(ofSize: 10)
        statusLabel.textColor = .white
        statusLabel.backgroundColor = UIColor(hex: 0x34C759)
        statusLabel.layer.cornerRadius = 4
        statusLabel.clipsToBounds = true
        statusLabel.textAlignment = .center
        checkImageView.tintColor = .white
        checkImageView.backgroundColor = UIColor.black.withAlphaComponent(0.35)
        checkImageView.layer.cornerRadius = 10
        nameLabel.font = .systemFont(ofSize: 11)
        nameLabel.textColor = AppColor.textPrimary
        nameLabel.lineBreakMode = .byTruncatingMiddle
        sizeLabel.font = .systemFont(ofSize: 10)
        sizeLabel.textColor = AppColor.textTertiary

        contentView.addSubview(imageView)
        imageView.addSubview(statusLabel)
        imageView.addSubview(checkImageView)
        contentView.addSubview(nameLabel)
        contentView.addSubview(sizeLabel)
        imageView.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview()
            make.height.equalTo(imageView.snp.width)
        }
        statusLabel.snp.makeConstraints { make in
            make.top.leading.equalToSuperview().offset(4)
            make.height.equalTo(18)
            make.width.equalTo(48)
        }
        checkImageView.snp.makeConstraints { make in
            make.top.trailing.equalToSuperview().inset(4)
            make.size.equalTo(20)
        }
        nameLabel.snp.makeConstraints { make in
            make.top.equalTo(imageView.snp.bottom).offset(4)
            make.leading.trailing.equalToSuperview()
        }
        sizeLabel.snp.makeConstraints { make in
            make.top.equalTo(nameLabel.snp.bottom).offset(2)
            make.leading.trailing.equalToSuperview()
        }
    }

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

    func apply(material: TravelAlbumMaterial, selectionMode: Bool, selected: Bool) {
        let urlString = material.coverUrl.isEmpty ? material.fileUrl : material.coverUrl
        if let url = URL(string: urlString), !urlString.isEmpty {
            imageView.kf.setImage(with: url, placeholder: UIImage(systemName: "photo"))
        } else {
            imageView.image = UIImage(systemName: "photo")
            imageView.tintColor = AppColor.primary
            imageView.backgroundColor = UIColor(hex: 0xEAF2FF)
        }
        checkImageView.isHidden = !selectionMode
        checkImageView.image = UIImage(systemName: selected ? "checkmark.circle.fill" : "circle")
        checkImageView.tintColor = selected ? AppColor.primary : .white
        nameLabel.text = material.fileName
        sizeLabel.text = TravelAlbumDisplayFormatter.fileSizeText(material.fileSize)
    }
}
