//
//  ScenicQueueViewController.swift
//  suixinkan
//

import SnapKit
import UIKit

/// 排队管理首页，严格对齐 Android `ScenicQueueScreen` 的布局与交互。
final class ScenicQueueViewController: BaseViewController {
    private let viewModel = ScenicQueueViewModel()
    private let api: ScenicQueueAPIProtocol

    private let punchSpotRow = UIView()
    private let punchSpotLabel = UILabel()
    private let statsBanner = ScenicQueueStatsBannerView()
    private let contentContainer = UIView()
    private let tabStrip = ScenicQueueTabStripView(titles: ["当前排队", "过号列表"])
    private let tableView = UITableView(frame: .zero, style: .plain)
    private let bottomBar = UIView()
    private let prepareCallButton = UIButton(type: .system)
    private let quickCallButton = UIButton(type: .system)
    private let emptyLabel = UILabel()
    private var dataSource: UITableViewDiffableDataSource<Int, ScenicQueueListItem>!

    private var selectedTab = 0

    @MainActor
    init(api: ScenicQueueAPIProtocol? = nil) {
        self.api = api ?? NetworkServices.shared.scenicQueueAPI
        super.init(nibName: nil, bundle: nil)
    }

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

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

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        viewModel.startQueueStatsPolling(api: api)
    }

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

    override func setupNavigationBar() {
        title = "排队管理"
        navigationItem.rightBarButtonItem = UIBarButtonItem(
            image: UIImage(systemName: "gearshape"),
            style: .plain,
            target: self,
            action: #selector(settingsTapped)
        )
    }

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

        punchSpotRow.backgroundColor = .white
        let locationIcon = UIImageView(image: UIImage(named: "queue_location"))
        locationIcon.contentMode = .scaleAspectFit
        punchSpotLabel.font = .systemFont(ofSize: 16)
        punchSpotLabel.textColor = UIColor.black.withAlphaComponent(0.7)
        punchSpotLabel.lineBreakMode = .byTruncatingTail
        punchSpotRow.addSubview(locationIcon)
        punchSpotRow.addSubview(punchSpotLabel)

        contentContainer.backgroundColor = .white
        contentContainer.layer.cornerRadius = ScenicQueueTokens.radiusContentSheetTop
        contentContainer.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
        contentContainer.layer.shadowColor = UIColor.black.cgColor
        contentContainer.layer.shadowOpacity = 0.08
        contentContainer.layer.shadowRadius = 4
        contentContainer.layer.shadowOffset = CGSize(width: 0, height: 2)

        tableView.backgroundColor = .white
        tableView.separatorStyle = .none
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 260
        tableView.delegate = self
        tableView.register(ScenicQueueTicketCell.self, forCellReuseIdentifier: ScenicQueueTicketCell.reuseIdentifier)
        tableView.register(ScenicQueueSkippedCell.self, forCellReuseIdentifier: ScenicQueueSkippedCell.reuseIdentifier)
        tableView.refreshControl = UIRefreshControl()
        tableView.refreshControl?.addTarget(self, action: #selector(refreshPulled), for: .valueChanged)
        configureDataSource()

        emptyLabel.textColor = AppColor.textTertiary
        emptyLabel.font = ScenicQueueTokens.emptyStateFont
        emptyLabel.textAlignment = .center

        bottomBar.backgroundColor = .white
        bottomBar.layer.shadowColor = UIColor.black.cgColor
        bottomBar.layer.shadowOpacity = 0.12
        bottomBar.layer.shadowRadius = 8
        bottomBar.layer.shadowOffset = CGSize(width: 0, height: -2)
        configureBottomButton(prepareCallButton, title: "准备叫号", subtitle: "服务人员操作", image: UIImage(systemName: "play.fill"), color: ScenicQueueTokens.bannerBlue)
        configureBottomButton(quickCallButton, title: "快速叫号", subtitle: "叫号人员操作", image: UIImage(systemName: "person.fill"), color: UIColor(hex: 0x7C3AED))

        view.addSubview(punchSpotRow)
        view.addSubview(statsBanner)
        view.addSubview(contentContainer)
        contentContainer.addSubview(tabStrip)
        contentContainer.addSubview(tableView)
        contentContainer.addSubview(emptyLabel)
        view.addSubview(bottomBar)
        bottomBar.addSubview(prepareCallButton)
        bottomBar.addSubview(quickCallButton)

        locationIcon.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(16)
            make.centerY.equalToSuperview()
            make.size.equalTo(24)
        }
        punchSpotLabel.snp.makeConstraints { make in
            make.leading.equalTo(locationIcon.snp.trailing).offset(6)
            make.trailing.equalToSuperview().offset(-16)
            make.centerY.equalToSuperview()
        }
    }

    override func setupConstraints() {
        punchSpotRow.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide)
            make.leading.trailing.equalToSuperview()
            make.height.equalTo(56)
        }
        statsBanner.snp.makeConstraints { make in
            make.top.equalTo(punchSpotRow.snp.bottom)
            make.leading.trailing.equalToSuperview()
            make.height.equalTo(96)
        }
        contentContainer.snp.makeConstraints { make in
            make.top.equalTo(statsBanner.snp.bottom).offset(16)
            make.leading.trailing.equalToSuperview().inset(16)
            make.bottom.equalTo(bottomBar.snp.top).offset(-8)
        }
        tabStrip.snp.makeConstraints { make in
            make.top.equalToSuperview()
            make.leading.trailing.equalToSuperview().inset(12)
            make.height.equalTo(48)
        }
        tableView.snp.makeConstraints { make in
            make.top.equalTo(tabStrip.snp.bottom)
            make.leading.trailing.bottom.equalToSuperview()
        }
        emptyLabel.snp.makeConstraints { make in
            make.center.equalTo(tableView)
        }
        bottomBar.snp.makeConstraints { make in
            make.leading.trailing.bottom.equalToSuperview()
        }
        prepareCallButton.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(10)
            make.leading.equalToSuperview().offset(16)
            make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-10)
            make.height.equalTo(68)
        }
        quickCallButton.snp.makeConstraints { make in
            make.top.bottom.width.equalTo(prepareCallButton)
            make.leading.equalTo(prepareCallButton.snp.trailing).offset(10)
            make.trailing.equalToSuperview().offset(-16)
        }
    }

    override func bindActions() {
        tabStrip.onSelect = { [weak self] index in self?.selectTab(index) }
        prepareCallButton.addTarget(self, action: #selector(prepareCallTapped), for: .touchUpInside)
        quickCallButton.addTarget(self, action: #selector(quickCallTapped), for: .touchUpInside)
        viewModel.onStateChange = { [weak self] in
            Task { @MainActor in self?.applyState() }
        }
        viewModel.onShowMessage = { [weak self] message in
            Task { @MainActor in self?.showToast(message) }
        }
        viewModel.onRequireSettings = { [weak self] in
            Task { @MainActor in self?.presentParametersRequiredDialog() }
        }
        viewModel.onNavigateSettings = { [weak self] in
            Task { @MainActor in self?.navigationController?.pushViewController(ScenicQueueSettingsViewController(), animated: true) }
        }
        viewModel.onNavigateBack = { [weak self] in
            Task { @MainActor in self?.navigationController?.popViewController(animated: true) }
        }
        NotificationCenter.default.addObserver(self, selector: #selector(handleQueueDidUpdate), name: NotificationName.scenicQueueDidUpdate, object: nil)
    }

    private func applyState() {
        punchSpotLabel.text = viewModel.selectedPunchSpotLine
        statsBanner.configure(summary: viewModel.summary)
        tableView.refreshControl?.endRefreshing()
        applySnapshot(animated: true)
        let isEmpty = selectedTab == 0 ? viewModel.currentQueue.isEmpty : viewModel.skippedQueue.isEmpty
        emptyLabel.text = selectedTab == 0 ? "暂无排队" : "暂无过号记录"
        emptyLabel.isHidden = !isEmpty
        prepareCallButton.isHidden = !viewModel.prepareCallButtonEnabled
        quickCallButton.isHidden = !viewModel.quickCallButtonEnabled
        prepareCallButton.setImage(UIImage(systemName: viewModel.prepareCallPlaying ? "pause.fill" : "play.fill"), for: .normal)
        bottomBar.isHidden = !viewModel.queueGatePassed || (!viewModel.prepareCallButtonEnabled && !viewModel.quickCallButtonEnabled)
    }

    private func configureDataSource() {
        dataSource = UITableViewDiffableDataSource<Int, ScenicQueueListItem>(tableView: tableView) { [weak self] tableView, indexPath, item in
            guard let self else { return UITableViewCell() }
            switch item {
            case .current(let ticket):
                let cell = tableView.dequeueReusableCell(withIdentifier: ScenicQueueTicketCell.reuseIdentifier, for: indexPath) as! ScenicQueueTicketCell
                cell.delegate = self
                cell.configure(
                    ticket: ticket,
                    shootingQueueNo: self.viewModel.shootingTimedQueueNo,
                    remainSeconds: self.viewModel.shootingRemainSeconds,
                    showStartShootingButton: self.viewModel.showStartShootingButton
                )
                return cell
            case .skipped(let ticket):
                let cell = tableView.dequeueReusableCell(withIdentifier: ScenicQueueSkippedCell.reuseIdentifier, for: indexPath) as! ScenicQueueSkippedCell
                cell.delegate = self
                cell.configure(ticket: ticket)
                return cell
            }
        }
    }

    private func applySnapshot(animated: Bool) {
        let previousItems = Set(dataSource.snapshot().itemIdentifiers)
        var snapshot = NSDiffableDataSourceSnapshot<Int, ScenicQueueListItem>()
        snapshot.appendSections([0])
        let items: [ScenicQueueListItem] = selectedTab == 0
            ? viewModel.currentQueue.map(ScenicQueueListItem.current)
            : viewModel.skippedQueue.map(ScenicQueueListItem.skipped)
        snapshot.appendItems(items)
        snapshot.reconfigureItems(items.filter(previousItems.contains))
        dataSource.apply(snapshot, animatingDifferences: animated)
    }

    private func configureBottomButton(_ button: UIButton, title: String, subtitle: String, image: UIImage?, color: UIColor) {
        var config = UIButton.Configuration.filled()
        config.baseBackgroundColor = color
        config.baseForegroundColor = .white
        config.image = image
        config.imagePadding = 10
        config.cornerStyle = .medium
        var titleAttributes = AttributeContainer()
        titleAttributes.font = UIFont.systemFont(ofSize: 15, weight: .semibold)
        var subtitleAttributes = AttributeContainer()
        subtitleAttributes.font = UIFont.systemFont(ofSize: 11)
        subtitleAttributes.foregroundColor = UIColor.white.withAlphaComponent(0.82)
        config.attributedTitle = AttributedString(title, attributes: titleAttributes)
        config.attributedSubtitle = AttributedString(subtitle, attributes: subtitleAttributes)
        button.configuration = config
        button.tintColor = .white
    }

    private func presentParametersRequiredDialog() {
        guard presentedViewController == nil else { return }
        let dialog = ScenicQueueConfirmationDialogViewController(
            configuration: ScenicQueueDialogConfiguration(
                title: "请先设置排队参数",
                message: "请在排队设置中选择并保存打卡点后，再使用排队管理。",
                emphasizedText: nil,
                dangerText: nil,
                cancelTitle: "暂不使用",
                confirmTitle: "去设置",
                buttonRadius: 22,
                dismissOnBackdrop: false
            ),
            onCancel: { [weak self] in self?.viewModel.exitQueueModule() },
            onConfirm: { [weak self] in self?.navigationController?.pushViewController(ScenicQueueSettingsViewController(), animated: true) }
        )
        present(dialog, animated: true)
    }

    private func presentConfirm(
        title: String,
        emphasizedText: String,
        dangerText: String? = nil,
        confirmTitle: String = "确认",
        cancel: @escaping () -> Void,
        confirm: @escaping () -> Void
    ) {
        let dialog = ScenicQueueConfirmationDialogViewController(
            configuration: ScenicQueueDialogConfiguration(
                title: title,
                message: nil,
                emphasizedText: emphasizedText,
                dangerText: dangerText,
                cancelTitle: "取消",
                confirmTitle: confirmTitle,
                buttonRadius: title == "确认完成拍摄" ? 22 : 8,
                dismissOnBackdrop: true
            ),
            onCancel: cancel,
            onConfirm: confirm
        )
        present(dialog, animated: true)
    }

    private func openDial(_ digits: String) {
        guard !digits.isEmpty else { return }
        present(ScenicQueueDialSheetViewController(digits: digits), animated: true)
    }

    @objc private func settingsTapped() {
        viewModel.openSettings()
    }

    private func selectTab(_ index: Int) {
        guard index != selectedTab else { return }
        selectedTab = index
        UIView.transition(with: tableView, duration: 0.22, options: .transitionCrossDissolve) {
            self.applySnapshot(animated: false)
        }
        applyState()
    }

    @objc private func refreshPulled() {
        Task {
            if selectedTab == 0 {
                await viewModel.refreshCurrentQueue(api: api)
            } else {
                await viewModel.refreshSkippedQueue(api: api)
            }
        }
    }

    @objc private func prepareCallTapped() {
        viewModel.togglePrepareCallPlayback()
    }

    @objc private func quickCallTapped() {
        Task { await viewModel.quickCallFirstTicket(api: api) }
    }

    @objc private func handleQueueDidUpdate() {
        Task {
            await viewModel.refreshQueueStats(api: api)
            await viewModel.refreshCurrentQueue(api: api)
            await viewModel.refreshSkippedQueue(api: api)
        }
    }
}

extension ScenicQueueViewController: UITableViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        guard scrollView.contentOffset.y > scrollView.contentSize.height - scrollView.bounds.height - 120 else { return }
        Task {
            if selectedTab == 0 {
                await viewModel.loadMoreCurrentQueue(api: api)
            } else {
                await viewModel.loadMoreSkippedQueue(api: api)
            }
        }
    }
}

extension ScenicQueueViewController: ScenicQueueTicketCellDelegate {
    func scenicQueueTicketCellDidTapDial(_ cell: ScenicQueueTicketCell, ticket: ScenicQueueTicket) {
        openDial(ticket.dialPhoneDigits)
    }

    func scenicQueueTicketCellDidTapSkip(_ cell: ScenicQueueTicketCell, ticket: ScenicQueueTicket) {
        viewModel.requestSkipTicket(recordId: ticket.recordId, queueNo: ticket.queueNo)
        presentConfirm(title: "确认过号", emphasizedText: ticket.queueNo, dangerText: "确认该用户未到场并过号", cancel: { [weak self] in
            self?.viewModel.dismissSkipDialog()
        }) { [weak self] in
            guard let self else { return }
            Task { await self.viewModel.confirmSkipTicket(api: self.api) }
        }
    }

    func scenicQueueTicketCellDidTapPrimary(_ cell: ScenicQueueTicketCell, ticket: ScenicQueueTicket) {
        if ticket.status == .waiting {
            viewModel.requestCallConfirm(recordId: ticket.recordId, queueNo: ticket.queueNo)
            presentConfirm(title: "确认叫号", emphasizedText: "确认叫号【\(ticket.queueNo)】", cancel: { [weak self] in
                self?.viewModel.dismissCallConfirmDialog()
            }) { [weak self] in
                guard let self else { return }
                Task { await self.viewModel.confirmCallTicket(api: self.api) }
            }
        } else {
            viewModel.startShooting(api: api, recordId: ticket.recordId, queueNo: ticket.queueNo)
        }
    }

    func scenicQueueTicketCellDidTapRecall(_ cell: ScenicQueueTicketCell, ticket: ScenicQueueTicket) {
        viewModel.requestCallConfirm(recordId: ticket.recordId, queueNo: ticket.queueNo, isRecall: true)
        presentConfirm(title: "重新叫号", emphasizedText: "确认叫号【\(ticket.queueNo)】", cancel: { [weak self] in
            self?.viewModel.dismissCallConfirmDialog()
        }) { [weak self] in
            guard let self else { return }
            Task { await self.viewModel.confirmCallTicket(api: self.api) }
        }
    }

    func scenicQueueTicketCellDidTapComplete(_ cell: ScenicQueueTicketCell, ticket: ScenicQueueTicket) {
        viewModel.requestFinishConfirm(recordId: ticket.recordId, queueNo: ticket.queueNo)
        presentConfirm(title: "确认完成拍摄", emphasizedText: ticket.queueNo, cancel: { [weak self] in
            self?.viewModel.dismissFinishDialog()
        }) { [weak self] in
            guard let self else { return }
            Task { await self.viewModel.confirmFinishTicket(api: self.api) }
        }
    }

    func scenicQueueTicketCellDidTapMark(_ cell: ScenicQueueTicketCell, ticket: ScenicQueueTicket) {
        viewModel.onTicketMarkClick(recordId: ticket.recordId, queueNo: ticket.queueNo, uid: ticket.uid)
        guard let pending = viewModel.pendingMark else { return }
        let dialog = ScenicQueueMarkDialogViewController(
            pending: pending,
            onCancel: { [weak self] in self?.viewModel.dismissMarkDialog() },
            onConfirm: { [weak self] marked, days in
                guard let self else { return }
                Task { await self.viewModel.confirmUserMark(api: self.api, markAsFreelancePhotog: marked, queueBanDays: days) }
            }
        )
        present(dialog, animated: true)
    }
}

extension ScenicQueueViewController: ScenicQueueSkippedCellDelegate {
    func scenicQueueSkippedCellDidTapDial(_ cell: ScenicQueueSkippedCell, ticket: ScenicQueueSkippedTicket) {
        openDial(ticket.dialPhoneDigits)
    }

    func scenicQueueSkippedCellDidTapRequeue(_ cell: ScenicQueueSkippedCell, ticket: ScenicQueueSkippedTicket) {
        viewModel.requestRequeueConfirm(recordId: ticket.recordId, queueNo: ticket.queueNo)
        presentConfirm(title: "确认重新排队", emphasizedText: ticket.queueNo, dangerText: "确认后将插入当前排队队列", confirmTitle: "确定", cancel: { [weak self] in
            self?.viewModel.dismissRequeueDialog()
        }) { [weak self] in
            guard let self else { return }
            Task { await self.viewModel.confirmRequeueTicket(api: self.api) }
        }
    }
}
