//
//  LiveManageViewController.swift
//  suixinkan
//

import Kingfisher
import PhotosUI
import SnapKit
import UIKit

/// 直播管理页，对齐 Android `AliveManageScreen`。
final class LiveManageViewController: BaseViewController, UITableViewDelegate {
    private enum Section {
        case main
    }

    private let viewModel = LiveManageViewModel()
    private let liveAPI: any LiveServing
    private let uploader: any LiveOSSUploading
    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 addButton = AppButton(title: "添加")
    private var dataSource: UITableViewDiffableDataSource<Section, LiveItem>!

    /// 初始化直播管理页。
    @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
        tableView.backgroundColor = .clear
        tableView.separatorStyle = .none
        tableView.delegate = self
        tableView.refreshControl = refreshControl
        tableView.register(LiveItemCell.self, forCellReuseIdentifier: LiveItemCell.reuseIdentifier)
        tableView.contentInset = UIEdgeInsets(top: 12, left: 0, bottom: 12, right: 0)

        dataSource = UITableViewDiffableDataSource<Section, LiveItem>(tableView: tableView) { [weak self] tableView, indexPath, item in
            guard let cell = tableView.dequeueReusableCell(withIdentifier: LiveItemCell.reuseIdentifier, for: indexPath) as? LiveItemCell else {
                return UITableViewCell()
            }
            cell.apply(item)
            cell.onCopy = { [weak self] in self?.copyPushURL(item) }
            cell.onControl = { [weak self] in self?.controlLive(item) }
            cell.onFinish = { [weak self] in self?.confirmFinish(item) }
            return cell
        }

        emptyLabel.text = "暂无直播"
        emptyLabel.font = .systemFont(ofSize: 14)
        emptyLabel.textColor = UIColor(hex: 0x4B5563)
        emptyLabel.textAlignment = .center
        emptyLabel.isHidden = true
        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.color = AppColor.primary

        bottomBar.backgroundColor = .white
        view.addSubview(tableView)
        view.addSubview(emptyLabel)
        view.addSubview(loadingIndicator)
        view.addSubview(bottomBar)
        bottomBar.addSubview(addButton)
    }

    override func setupConstraints() {
        bottomBar.snp.makeConstraints { make in
            make.leading.trailing.bottom.equalToSuperview()
        }
        addButton.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(16)
            make.leading.trailing.equalToSuperview().inset(16)
            make.bottom.equalTo(view.safeAreaLayoutGuide).inset(16)
            make.height.equalTo(48)
        }
        tableView.snp.makeConstraints { make in
            make.top.leading.trailing.equalTo(view.safeAreaLayoutGuide)
            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) }
        }
        viewModel.onLiveCreated = { [weak self] in
            Task { @MainActor in self?.dismiss(animated: true) }
        }
        refreshControl.addTarget(self, action: #selector(refreshTriggered), for: .valueChanged)
        addButton.addTarget(self, action: #selector(showAddLiveSheet), for: .touchUpInside)
    }

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

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        guard let item = dataSource.itemIdentifier(for: indexPath) else { return }
        navigationController?.pushViewController(LiveDetailViewController(liveId: item.id), animated: true)
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        UITableView.automaticDimension
    }

    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 showAddLiveSheet() {
        let controller = AddLiveSheetViewController(uploader: uploader)
        controller.onConfirm = { [weak self] title, cover in
            guard let self else { return }
            Task { await self.viewModel.createLive(title: title, coverUrl: cover, api: self.liveAPI) }
        }
        controller.onMessage = { [weak self] message in
            self?.showToast(message)
        }
        if let sheet = controller.sheetPresentationController {
            sheet.detents = [.medium(), .large()]
            sheet.prefersGrabberVisible = true
        }
        present(controller, animated: true)
    }

    private func applyViewModel() {
        if viewModel.isRefreshing {
            if !refreshControl.isRefreshing { refreshControl.beginRefreshing() }
        } else {
            refreshControl.endRefreshing()
        }
        viewModel.isLoading && viewModel.items.isEmpty ? loadingIndicator.startAnimating() : loadingIndicator.stopAnimating()
        emptyLabel.isHidden = viewModel.isLoading || !viewModel.items.isEmpty
        var snapshot = NSDiffableDataSourceSnapshot<Section, LiveItem>()
        snapshot.appendSections([.main])
        snapshot.appendItems(viewModel.items)
        dataSource.apply(snapshot, animatingDifferences: true)
    }

    private func copyPushURL(_ item: LiveItem) {
        UIPasteboard.general.string = viewModel.copyPushURL(item)
        showToast("已复制")
    }

    private func controlLive(_ item: LiveItem) {
        Task { await viewModel.controlLive(item, api: liveAPI) }
    }

    private func confirmFinish(_ item: LiveItem) {
        showAlert(title: "确认结束", message: "是否确认结束该直播？") { [weak self] in
            guard let self else { return }
            Task { await self.viewModel.finishLive(item, api: self.liveAPI) }
        }
    }
}

/// 直播列表项 Cell，对齐 Android `AliveItem`。
private final class LiveItemCell: UITableViewCell {
    static let reuseIdentifier = "LiveItemCell"

    var onCopy: (() -> Void)?
    var onControl: (() -> Void)?
    var onFinish: (() -> Void)?

    private let container = UIView()
    private let coverImageView = LiveCoverImageView()
    private let statusOverlay = UIView()
    private let statusDot = UIView()
    private let statusLabel = UILabel()
    private let titleLabel = UILabel()
    private let timeLabel = UILabel()
    private let durationLabel = UILabel()
    private let copyButton = UIButton(type: .system)
    private let controlButton = LiveActionButton(title: "开始", image: UIImage(systemName: "play.fill"))
    private let finishButton = LiveActionButton(title: "结束", image: UIImage(systemName: "stop.fill"))

    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()
        onCopy = nil
        onControl = nil
        onFinish = nil
    }

    /// 应用直播列表项。
    func apply(_ item: LiveItem) {
        coverImageView.setURL(item.coverImg)
        statusLabel.text = item.statusLabel
        statusDot.backgroundColor = item.liveStatus == .living ? UIColor(hex: 0xF91616) : .white
        titleLabel.text = item.displayTitle
        timeLabel.text = "直播时间：\(LiveUIFormatter.timeRange(start: item.startTime, end: item.endTime))"
        durationLabel.text = "时长：\(LiveUIFormatter.duration(item.duration))"
        controlButton.setTitle(item.controlTitle, for: .normal)
        controlButton.setImage(UIImage(systemName: item.liveStatus == .living ? "pause.fill" : "play.fill"), for: .normal)
        controlButton.buttonStyle = item.liveStatus == .living ? .warning : .primary
        controlButton.isEnabled = item.liveStatus.isOperable
        finishButton.buttonStyle = .danger
        finishButton.isEnabled = item.liveStatus.isOperable
    }

    private func setup() {
        selectionStyle = .none
        backgroundColor = .clear
        contentView.backgroundColor = .clear
        container.backgroundColor = .white

        statusOverlay.backgroundColor = UIColor.black.withAlphaComponent(0.35)
        statusOverlay.layer.cornerRadius = 8
        statusOverlay.clipsToBounds = true
        statusDot.layer.cornerRadius = 3
        statusLabel.font = .systemFont(ofSize: 12)
        statusLabel.textColor = .white
        titleLabel.font = .systemFont(ofSize: 16, weight: .medium)
        titleLabel.textColor = AppColor.textPrimary
        titleLabel.numberOfLines = 1
        timeLabel.font = .systemFont(ofSize: 12)
        timeLabel.textColor = AppColor.textPrimary
        durationLabel.font = .systemFont(ofSize: 12)
        durationLabel.textColor = AppColor.textPrimary
        copyButton.setTitle("复制地址", for: .normal)
        copyButton.titleLabel?.font = .systemFont(ofSize: 12)
        copyButton.setTitleColor(.white, for: .normal)
        copyButton.backgroundColor = AppColor.primary
        copyButton.layer.cornerRadius = 4
        finishButton.buttonStyle = .danger

        contentView.addSubview(container)
        container.addSubview(coverImageView)
        coverImageView.addSubview(statusOverlay)
        statusOverlay.addSubview(statusDot)
        statusOverlay.addSubview(statusLabel)
        container.addSubview(titleLabel)
        container.addSubview(timeLabel)
        container.addSubview(durationLabel)
        container.addSubview(copyButton)
        container.addSubview(controlButton)
        container.addSubview(finishButton)

        container.snp.makeConstraints { make in
            make.top.bottom.equalToSuperview()
            make.leading.trailing.equalToSuperview()
        }
        coverImageView.snp.makeConstraints { make in
            make.top.leading.equalToSuperview().offset(16)
            make.size.equalTo(CGSize(width: 120, height: 68))
        }
        statusOverlay.snp.makeConstraints { make in
            make.leading.bottom.equalToSuperview().inset(6)
            make.height.equalTo(20)
        }
        statusDot.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(6)
            make.centerY.equalToSuperview()
            make.size.equalTo(6)
        }
        statusLabel.snp.makeConstraints { make in
            make.leading.equalTo(statusDot.snp.trailing).offset(2)
            make.trailing.equalToSuperview().inset(6)
            make.centerY.equalToSuperview()
        }
        titleLabel.snp.makeConstraints { make in
            make.top.equalTo(coverImageView)
            make.leading.equalTo(coverImageView.snp.trailing).offset(12)
            make.trailing.equalToSuperview().inset(16)
        }
        timeLabel.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(4)
            make.leading.trailing.equalTo(titleLabel)
        }
        durationLabel.snp.makeConstraints { make in
            make.leading.equalTo(titleLabel)
            make.bottom.equalTo(coverImageView)
        }
        copyButton.snp.makeConstraints { make in
            make.trailing.equalToSuperview().inset(16)
            make.centerY.equalTo(durationLabel)
            make.height.equalTo(22)
            make.width.equalTo(64)
        }
        controlButton.snp.makeConstraints { make in
            make.top.equalTo(coverImageView.snp.bottom).offset(20)
            make.leading.equalToSuperview().offset(16)
            make.height.equalTo(40)
            make.bottom.equalToSuperview().inset(16)
        }
        finishButton.snp.makeConstraints { make in
            make.leading.equalTo(controlButton.snp.trailing).offset(8)
            make.trailing.equalToSuperview().inset(16)
            make.top.bottom.width.equalTo(controlButton)
        }

        copyButton.addTarget(self, action: #selector(copyTapped), for: .touchUpInside)
        controlButton.addTarget(self, action: #selector(controlTapped), for: .touchUpInside)
        finishButton.addTarget(self, action: #selector(finishTapped), for: .touchUpInside)
    }

    @objc private func copyTapped() {
        onCopy?()
    }

    @objc private func controlTapped() {
        onControl?()
    }

    @objc private func finishTapped() {
        onFinish?()
    }
}

/// 新增直播底部弹窗，对齐 Android `AddAliveModal`。
private final class AddLiveSheetViewController: UIViewController, PHPickerViewControllerDelegate {
    var onConfirm: ((String, String) -> Void)?
    var onMessage: ((String) -> Void)?

    private let uploader: any LiveOSSUploading
    private let titleLabel = UILabel()
    private let titleField = UITextField()
    private let coverTitleLabel = UILabel()
    private let uploadView = LiveDashedUploadView()
    private let coverImageView = LiveCoverImageView()
    private let confirmButton = AppButton(title: "确认")
    private let loadingIndicator = UIActivityIndicatorView(style: .medium)
    private var coverURL = ""

    /// 初始化新增直播弹窗。
    init(uploader: any LiveOSSUploading) {
        self.uploader = uploader
        super.init(nibName: nil, bundle: nil)
    }

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

    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
    }

    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 uploadCover(media)
            } catch {
                onMessage?(error.localizedDescription)
            }
        }
    }

    private func setup() {
        view.backgroundColor = .white
        let headingLabel = UILabel()
        headingLabel.text = "新增直播"
        headingLabel.font = .systemFont(ofSize: 18, weight: .semibold)
        headingLabel.textColor = AppColor.textPrimary
        headingLabel.textAlignment = .center
        titleLabel.text = "直播标题"
        titleLabel.font = .systemFont(ofSize: 16, weight: .medium)
        titleLabel.textColor = AppColor.textPrimary
        titleField.placeholder = "请输入直播标题"
        titleField.font = .systemFont(ofSize: 14)
        titleField.borderStyle = .none
        titleField.backgroundColor = .white
        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
        coverTitleLabel.text = "封面图片"
        coverTitleLabel.font = .systemFont(ofSize: 16, weight: .medium)
        coverTitleLabel.textColor = AppColor.textPrimary
        coverImageView.isHidden = true
        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.color = AppColor.primary

        view.addSubview(headingLabel)
        view.addSubview(titleLabel)
        view.addSubview(titleField)
        view.addSubview(coverTitleLabel)
        view.addSubview(uploadView)
        view.addSubview(coverImageView)
        view.addSubview(loadingIndicator)
        view.addSubview(confirmButton)

        headingLabel.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide).offset(12)
            make.leading.trailing.equalToSuperview().inset(16)
        }
        titleLabel.snp.makeConstraints { make in
            make.top.equalTo(headingLabel.snp.bottom).offset(18)
            make.leading.trailing.equalToSuperview().inset(16)
        }
        titleField.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(8)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(44)
        }
        coverTitleLabel.snp.makeConstraints { make in
            make.top.equalTo(titleField.snp.bottom).offset(12)
            make.leading.trailing.equalToSuperview().inset(16)
        }
        uploadView.snp.makeConstraints { make in
            make.top.equalTo(coverTitleLabel.snp.bottom).offset(8)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(uploadView.snp.width).multipliedBy(9.0 / 16.0)
        }
        coverImageView.snp.makeConstraints { make in
            make.edges.equalTo(uploadView)
        }
        loadingIndicator.snp.makeConstraints { make in
            make.center.equalTo(uploadView)
        }
        confirmButton.snp.makeConstraints { make in
            make.top.equalTo(uploadView.snp.bottom).offset(32)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(48)
            make.bottom.lessThanOrEqualTo(view.safeAreaLayoutGuide).inset(16)
        }

        uploadView.addTarget(self, action: #selector(pickCover), for: .touchUpInside)
        confirmButton.addTarget(self, action: #selector(confirmTapped), for: .touchUpInside)
    }

    @objc private func pickCover() {
        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() {
        onConfirm?(titleField.text ?? "", coverURL)
    }

    private func uploadCover(_ media: LivePickedMedia) async {
        loadingIndicator.startAnimating()
        defer { loadingIndicator.stopAnimating() }
        do {
            let scenicId = AppStore.shared.session.currentScenicId
            let url = try await uploader.uploadLiveCover(
                data: media.data,
                fileName: media.fileName,
                scenicId: scenicId,
                onProgress: { _ in }
            )
            coverURL = url
            coverImageView.image = UIImage(data: media.data)
            coverImageView.isHidden = false
            uploadView.isHidden = true
        } catch {
            onMessage?(error.localizedDescription.isEmpty ? "上传失败" : error.localizedDescription)
        }
    }
}
