//
//  SampleDetailViewController.swift
//  suixinkan
//

import AVFoundation
import Kingfisher
import SnapKit
import UIKit

/// 样片详情页，对齐 Android `SampleDetailScreen`。
final class SampleDetailViewController: BaseViewController {
    private let viewModel: SampleDetailViewModel
    private let api: any SampleManagementServing

    private let scrollView = UIScrollView()
    private let contentStack = UIStackView()
    private let carouselView = SampleMediaCarouselView()
    private let sampleInfoSection = SampleDetailSampleInfoSection()
    private let uploaderSection = SampleDetailUploaderSection()
    private let scenicSection = SampleDetailImageInfoSection(title: "打卡地点")
    private let projectSection = SampleDetailImageInfoSection(title: "样片绑定套餐")
    private let reviewSection = SampleDetailReviewSection()

    /// 初始化样片详情页。
    init(
        sampleId: Int,
        api: any SampleManagementServing = NetworkServices.shared.sampleManagementAPI
    ) {
        viewModel = SampleDetailViewModel(sampleId: sampleId)
        self.api = api
        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 = UIColor(hex: 0xF4F4F4)
        contentStack.axis = .vertical
        contentStack.spacing = 12
        scrollView.backgroundColor = UIColor(hex: 0xF4F4F4)

        view.addSubview(scrollView)
        scrollView.addSubview(contentStack)
        contentStack.addArrangedSubview(carouselView)
        contentStack.addArrangedSubview(sampleInfoSection)
        contentStack.addArrangedSubview(uploaderSection)
        contentStack.addArrangedSubview(scenicSection)
        contentStack.addArrangedSubview(projectSection)
        contentStack.addArrangedSubview(reviewSection)
    }

    override func setupConstraints() {
        scrollView.snp.makeConstraints { make in
            make.edges.equalTo(view.safeAreaLayoutGuide)
        }
        contentStack.snp.makeConstraints { make in
            make.edges.equalToSuperview()
            make.width.equalTo(scrollView)
        }
        carouselView.snp.makeConstraints { make in
            make.height.equalTo(carouselView.snp.width).multipliedBy(9.0 / 16.0)
        }
    }

    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) }
        }
    }

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

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

    private func applyViewModel() {
        if viewModel.isLoading && viewModel.detail == nil {
            showLoading()
        } else {
            hideLoading()
        }
        guard let detail = viewModel.detail else { return }
        carouselView.apply(media: detail.mediaList ?? [])
        sampleInfoSection.apply(detail: detail)
        uploaderSection.apply(detail: detail)
        scenicSection.applyScenic(detail: detail)
        projectSection.applyProject(detail: detail)
        reviewSection.apply(detail: detail)
    }
}

/// 样片详情媒体轮播，支持图片自动切换与视频播完切换。
private final class SampleMediaCarouselView: UIView, UIScrollViewDelegate {
    private let scrollView = UIScrollView()
    private let pageControl = UIPageControl()
    private let placeholderLabel = UILabel()
    private var media: [SampleDetailMediaItem] = []
    private var players: [Int: AVPlayer] = [:]
    private var timer: Timer?

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(hex: 0xF5F5F5)
        scrollView.isPagingEnabled = true
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.delegate = self
        scrollView.bounces = false
        pageControl.currentPageIndicatorTintColor = .white
        pageControl.pageIndicatorTintColor = UIColor.white.withAlphaComponent(0.5)
        placeholderLabel.text = "暂无媒体"
        placeholderLabel.font = .systemFont(ofSize: 14)
        placeholderLabel.textColor = AppColor.textSecondary
        placeholderLabel.textAlignment = .center

        addSubview(scrollView)
        addSubview(pageControl)
        addSubview(placeholderLabel)
        scrollView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        pageControl.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.bottom.equalToSuperview().inset(8)
        }
        placeholderLabel.snp.makeConstraints { make in
            make.center.equalToSuperview()
        }
    }

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

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

    /// 应用媒体列表。
    func apply(media: [SampleDetailMediaItem]) {
        stopTimer()
        NotificationCenter.default.removeObserver(self)
        players.values.forEach { $0.pause() }
        players.removeAll()
        self.media = media
        scrollView.subviews.forEach { $0.removeFromSuperview() }
        pageControl.numberOfPages = media.count
        pageControl.currentPage = 0
        pageControl.isHidden = media.count <= 1
        placeholderLabel.isHidden = !media.isEmpty
        scrollView.isHidden = media.isEmpty
        guard !media.isEmpty else { return }

        for (index, item) in media.enumerated() {
            let page = UIView()
            page.backgroundColor = UIColor(hex: 0xF5F5F5)
            page.tag = index
            scrollView.addSubview(page)
            if item.type == 2 {
                addVideo(urlText: item.displayURL, to: page, index: index)
            } else {
                addImage(urlText: item.displayURL, to: page)
            }
        }
        setNeedsLayout()
        layoutIfNeeded()
        playCurrentPageIfNeeded()
    }

    /// 暂停当前轮播。
    func pause() {
        stopTimer()
        players.values.forEach { $0.pause() }
    }

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        updateCurrentPage()
    }

    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        updateCurrentPage()
    }

    private func addImage(urlText: String, to page: UIView) {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        page.addSubview(imageView)
        imageView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        if let url = URL(string: urlText), !urlText.isEmpty {
            imageView.kf.setImage(with: url, placeholder: UIImage(named: "img_square_loading_big"))
        }
    }

    private func addVideo(urlText: String, to page: UIView, index: Int) {
        guard let url = URL(string: urlText), !urlText.isEmpty else {
            addImage(urlText: "", to: page)
            return
        }
        let player = AVPlayer(url: url)
        players[index] = player
        let playerView = SamplePlayerLayerView()
        playerView.playerLayer.player = player
        page.addSubview(playerView)
        playerView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(videoDidEnd(_:)),
            name: .AVPlayerItemDidPlayToEndTime,
            object: player.currentItem
        )
    }

    private func layoutPages() {
        let size = bounds.size
        guard size.width > 0, size.height > 0 else { return }
        for (index, page) in scrollView.subviews.enumerated() {
            page.frame = CGRect(x: CGFloat(index) * size.width, y: 0, width: size.width, height: size.height)
        }
        scrollView.contentSize = CGSize(width: size.width * CGFloat(media.count), height: size.height)
        scrollView.contentOffset = CGPoint(x: CGFloat(pageControl.currentPage) * size.width, y: 0)
    }

    private func updateCurrentPage() {
        guard bounds.width > 0 else { return }
        let page = Int(round(scrollView.contentOffset.x / bounds.width))
        pageControl.currentPage = max(0, min(page, media.count - 1))
        playCurrentPageIfNeeded()
    }

    private func playCurrentPageIfNeeded() {
        stopTimer()
        players.forEach { index, player in
            if index == pageControl.currentPage {
                player.seek(to: .zero)
                player.play()
            } else {
                player.pause()
            }
        }
        guard !media.isEmpty else { return }
        if media[pageControl.currentPage].type == 1 {
            startImageTimer()
        }
    }

    private func startImageTimer() {
        guard media.count > 1 else { return }
        timer = Timer.scheduledTimer(withTimeInterval: 3, repeats: false) { [weak self] _ in
            self?.advancePage()
        }
    }

    private func stopTimer() {
        timer?.invalidate()
        timer = nil
    }

    @objc private func videoDidEnd(_ notification: Notification) {
        advancePage()
    }

    private func advancePage() {
        guard media.count > 1, bounds.width > 0 else { return }
        let nextPage = (pageControl.currentPage + 1) % media.count
        pageControl.currentPage = nextPage
        scrollView.setContentOffset(CGPoint(x: CGFloat(nextPage) * bounds.width, y: 0), animated: true)
        if !scrollView.isDragging && !scrollView.isDecelerating {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak self] in
                self?.playCurrentPageIfNeeded()
            }
        }
    }
}

/// AVPlayerLayer 容器。
private final class SamplePlayerLayerView: UIView {
    override class var layerClass: AnyClass { AVPlayerLayer.self }
    var playerLayer: AVPlayerLayer { layer as! AVPlayerLayer }
}

/// 样片详情名称与上架状态区。
private final class SampleDetailSampleInfoSection: UIView {
    private let titleLabel = UILabel()
    private let listingBadge = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        titleLabel.font = .systemFont(ofSize: 20, weight: .bold)
        titleLabel.textColor = UIColor(hex: 0x2E3746)
        titleLabel.numberOfLines = 0
        listingBadge.font = .systemFont(ofSize: 12)
        listingBadge.layer.cornerRadius = 4
        listingBadge.clipsToBounds = true
        listingBadge.textAlignment = .center
        addSubview(titleLabel)
        addSubview(listingBadge)
        titleLabel.snp.makeConstraints { make in
            make.top.bottom.equalToSuperview().inset(16)
            make.leading.equalToSuperview().offset(16)
            make.trailing.lessThanOrEqualTo(listingBadge.snp.leading).offset(-12)
        }
        listingBadge.snp.makeConstraints { make in
            make.trailing.equalToSuperview().inset(16)
            make.centerY.equalTo(titleLabel)
            make.height.equalTo(24)
            make.width.greaterThanOrEqualTo(54)
        }
    }

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

    func apply(detail: SampleDetail) {
        titleLabel.text = detail.name ?? ""
        let listed = detail.listingStatus == 1
        listingBadge.text = listed ? "已上架" : "未上架"
        let color = listed ? UIColor(hex: 0x22C55E) : AppColor.textSecondary
        listingBadge.textColor = color
        listingBadge.backgroundColor = color.withAlphaComponent(0.1)
    }
}

/// 样片上传人信息区。
private final class SampleDetailUploaderSection: UIView {
    private let titleLabel = UILabel()
    private let avatarView = UIImageView()
    private let nameLabel = UILabel()
    private let tagStack = UIStackView()
    private let descriptionLabel = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        titleLabel.text = "上传人"
        titleLabel.font = .systemFont(ofSize: 14, weight: .bold)
        titleLabel.textColor = .black
        avatarView.contentMode = .scaleAspectFill
        avatarView.clipsToBounds = true
        avatarView.layer.cornerRadius = 24
        avatarView.backgroundColor = UIColor(hex: 0xF5F5F5)
        nameLabel.font = .systemFont(ofSize: 14, weight: .medium)
        nameLabel.textColor = UIColor(hex: 0x002255)
        descriptionLabel.font = .systemFont(ofSize: 14)
        descriptionLabel.textColor = UIColor(hex: 0x7B8EAA)
        descriptionLabel.numberOfLines = 0
        tagStack.axis = .horizontal
        tagStack.spacing = 8

        addSubview(titleLabel)
        addSubview(avatarView)
        addSubview(nameLabel)
        addSubview(tagStack)
        addSubview(descriptionLabel)

        titleLabel.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview().inset(16)
        }
        avatarView.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(12)
            make.leading.equalToSuperview().offset(16)
            make.size.equalTo(48)
            make.bottom.lessThanOrEqualToSuperview().inset(16)
        }
        nameLabel.snp.makeConstraints { make in
            make.top.equalTo(avatarView)
            make.leading.equalTo(avatarView.snp.trailing).offset(12)
        }
        tagStack.snp.makeConstraints { make in
            make.leading.equalTo(nameLabel.snp.trailing).offset(8)
            make.centerY.equalTo(nameLabel)
            make.trailing.lessThanOrEqualToSuperview().inset(16)
        }
        descriptionLabel.snp.makeConstraints { make in
            make.top.equalTo(nameLabel.snp.bottom).offset(4)
            make.leading.equalTo(nameLabel)
            make.trailing.equalToSuperview().inset(16)
            make.bottom.equalToSuperview().inset(16)
        }
    }

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

    func apply(detail: SampleDetail) {
        nameLabel.text = detail.uploaderName ?? ""
        descriptionLabel.text = detail.uploaderDescription ?? ""
        tagStack.arrangedSubviews.forEach { $0.removeFromSuperview() }
        if detail.platformCertification {
            tagStack.addArrangedSubview(makeTag("平台认证"))
        }
        if detail.scenicCertification {
            tagStack.addArrangedSubview(makeTag("景区认证"))
        }
        if let urlText = detail.uploaderAvatar, let url = URL(string: urlText), !urlText.isEmpty {
            avatarView.kf.setImage(with: url, placeholder: UIImage(systemName: "person.crop.circle.fill"))
        } else {
            avatarView.image = UIImage(systemName: "person.crop.circle.fill")
            avatarView.tintColor = AppColor.textTertiary
        }
    }

    private func makeTag(_ title: String) -> UILabel {
        let label = UILabel()
        label.text = title
        label.textColor = .white
        label.font = .systemFont(ofSize: 8)
        label.textAlignment = .center
        label.backgroundColor = AppColor.primary
        label.layer.cornerRadius = 4
        label.clipsToBounds = true
        label.snp.makeConstraints { make in
            make.height.equalTo(16)
            make.width.greaterThanOrEqualTo(44)
        }
        return label
    }
}

/// 样片详情图片信息区，复用打卡地点与绑定套餐布局。
private final class SampleDetailImageInfoSection: UIView {
    private let sectionTitleLabel = UILabel()
    private let imageView = UIImageView()
    private let titleLabel = UILabel()
    private let firstLineLabel = UILabel()
    private let secondLineLabel = UILabel()

    init(title: String) {
        super.init(frame: .zero)
        backgroundColor = .white
        sectionTitleLabel.text = title
        sectionTitleLabel.font = .systemFont(ofSize: 14, weight: .bold)
        sectionTitleLabel.textColor = .black
        imageView.backgroundColor = UIColor(hex: 0xF5F5F5)
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        imageView.layer.cornerRadius = 12
        titleLabel.font = .systemFont(ofSize: title == "打卡地点" ? 14 : 16, weight: .bold)
        titleLabel.textColor = .black
        [firstLineLabel, secondLineLabel].forEach { label in
            label.font = .systemFont(ofSize: 12)
            label.textColor = UIColor(hex: 0x4B5563)
            label.numberOfLines = 1
        }

        addSubview(sectionTitleLabel)
        addSubview(imageView)
        addSubview(titleLabel)
        addSubview(firstLineLabel)
        addSubview(secondLineLabel)
        sectionTitleLabel.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview().inset(16)
        }
        imageView.snp.makeConstraints { make in
            make.top.equalTo(sectionTitleLabel.snp.bottom).offset(12)
            make.leading.equalToSuperview().offset(16)
            make.height.equalTo(100)
            make.width.equalTo(179)
            make.bottom.equalToSuperview().inset(16)
        }
        titleLabel.snp.makeConstraints { make in
            make.top.equalTo(imageView).offset(2)
            make.leading.equalTo(imageView.snp.trailing).offset(12)
            make.trailing.equalToSuperview().inset(16)
        }
        firstLineLabel.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(12)
            make.leading.trailing.equalTo(titleLabel)
        }
        secondLineLabel.snp.makeConstraints { make in
            make.top.equalTo(firstLineLabel.snp.bottom).offset(7)
            make.leading.trailing.equalTo(titleLabel)
        }
    }

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

    func applyScenic(detail: SampleDetail) {
        titleLabel.text = detail.scenicName ?? ""
        firstLineLabel.attributedText = coloredValue(prefix: "无人机: ", value: "\(detail.scenicPlanesNum)架")
        secondLineLabel.attributedText = coloredValue(prefix: "摄影师: ", value: "\(detail.scenicPhotographerNum)人")
        setImage(detail.scenicCoverImg)
    }

    func applyProject(detail: SampleDetail) {
        titleLabel.text = detail.projectName ?? ""
        if let price = detail.projectPrice {
            firstLineLabel.attributedText = coloredValue(prefix: "价格: ", value: "\(price)元")
        } else {
            firstLineLabel.text = ""
        }
        if let deposit = detail.projectPriceDeposit {
            secondLineLabel.attributedText = coloredValue(prefix: "定金: ", value: "\(deposit)元")
        } else {
            secondLineLabel.text = ""
        }
        setImage(detail.projectCover)
    }

    private func setImage(_ urlText: String?) {
        if let urlText, let url = URL(string: urlText), !urlText.isEmpty {
            imageView.kf.setImage(with: url)
        } else {
            imageView.image = nil
        }
    }

    private func coloredValue(prefix: String, value: String) -> NSAttributedString {
        let text = NSMutableAttributedString(
            string: prefix,
            attributes: [.foregroundColor: UIColor(hex: 0x4B5563), .font: UIFont.systemFont(ofSize: 12)]
        )
        text.append(
            NSAttributedString(
                string: value,
                attributes: [.foregroundColor: AppColor.primary, .font: UIFont.systemFont(ofSize: 12)]
            )
        )
        return text
    }
}

/// 样片审核信息区。
private final class SampleDetailReviewSection: UIView {
    private let stack = UIStackView()
    private let titleLabel = UILabel()
    private let reviewerRow = SampleDetailInfoRow()
    private let reviewTimeRow = SampleDetailInfoRow()
    private let statusRow = SampleDetailStatusRow()
    private let noteRow = SampleDetailInfoRow()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        stack.axis = .vertical
        stack.spacing = 0
        titleLabel.text = "审核信息"
        titleLabel.font = .systemFont(ofSize: 14, weight: .bold)
        titleLabel.textColor = .black
        addSubview(stack)
        stack.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(16)
        }
        stack.addArrangedSubview(titleLabel)
        [reviewerRow, reviewTimeRow, statusRow, noteRow].forEach { row in
            stack.addArrangedSubview(row)
        }
    }

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

    func apply(detail: SampleDetail) {
        reviewerRow.apply(label: "审核人", value: detail.reviewer?.nonEmpty ?? "--")
        reviewTimeRow.apply(label: "审核时间", value: detail.reviewTime?.nonEmpty ?? "--")
        statusRow.apply(status: detail.status)
        noteRow.apply(label: "审核备注", value: detail.reviewNotes?.nonEmpty ?? "--", valueColor: UIColor(hex: 0x4B5563), valueFont: .systemFont(ofSize: 12))
    }
}

/// 样片详情普通信息行。
private final class SampleDetailInfoRow: UIView {
    private let label = UILabel()
    private let valueLabel = UILabel()
    private let separator = UIView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        label.font = .systemFont(ofSize: 14)
        label.textColor = UIColor(hex: 0x2E3746)
        valueLabel.font = .systemFont(ofSize: 14, weight: .medium)
        valueLabel.textColor = .black
        valueLabel.textAlignment = .right
        valueLabel.numberOfLines = 1
        separator.backgroundColor = UIColor(hex: 0xEEEEEE)
        addSubview(label)
        addSubview(valueLabel)
        addSubview(separator)
        snp.makeConstraints { make in
            make.height.equalTo(44)
        }
        label.snp.makeConstraints { make in
            make.leading.centerY.equalToSuperview()
        }
        valueLabel.snp.makeConstraints { make in
            make.trailing.centerY.equalToSuperview()
            make.leading.greaterThanOrEqualTo(label.snp.trailing).offset(12)
        }
        separator.snp.makeConstraints { make in
            make.leading.trailing.bottom.equalToSuperview()
            make.height.equalTo(1)
        }
    }

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

    func apply(label: String, value: String, valueColor: UIColor = .black, valueFont: UIFont = .systemFont(ofSize: 14, weight: .medium)) {
        self.label.text = label
        valueLabel.text = value
        valueLabel.textColor = valueColor
        valueLabel.font = valueFont
    }
}

/// 样片详情审核状态行。
private final class SampleDetailStatusRow: UIView {
    private let label = UILabel()
    private let badge = SampleStatusBadgeView()
    private let separator = UIView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        label.text = "审核状态"
        label.font = .systemFont(ofSize: 14)
        label.textColor = UIColor(hex: 0x2E3746)
        separator.backgroundColor = UIColor(hex: 0xEEEEEE)
        addSubview(label)
        addSubview(badge)
        addSubview(separator)
        snp.makeConstraints { make in
            make.height.equalTo(44)
        }
        label.snp.makeConstraints { make in
            make.leading.centerY.equalToSuperview()
        }
        badge.snp.makeConstraints { make in
            make.trailing.centerY.equalToSuperview()
            make.height.equalTo(24)
        }
        separator.snp.makeConstraints { make in
            make.leading.trailing.bottom.equalToSuperview()
            make.height.equalTo(1)
        }
    }

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

    func apply(status: Int) {
        badge.apply(status: status)
    }
}

private extension String {
    var nonEmpty: String? { isEmpty ? nil : self }
}
