//
//  WildPhotographerReportSubmitViewController.swift
//  suixinkan
//

import SnapKit
import UIKit

/// 提交举报页面，提供类型、证据、说明、定位和联系方式表单。
final class WildPhotographerReportSubmitViewController: BaseViewController {
    private let viewModel: WildPhotographerReportSubmitViewModel
    private let homeViewModel: WildPhotographerReportHomeViewModel
    private let scrollView = UIScrollView()
    private let contentStack = UIStackView()
    private let descriptionView = UITextView()
    private let contactField = UITextField()
    private let submitButton = UIButton(type: .system)

    init(
        homeViewModel: WildPhotographerReportHomeViewModel,
        locationProvider: any LocationProviding = LocationProvider.shared
    ) {
        self.homeViewModel = homeViewModel
        self.viewModel = WildPhotographerReportSubmitViewModel(
            homeViewModel: homeViewModel,
            locationProvider: locationProvider
        )
        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.pageBackgroundSoft
        scrollView.keyboardDismissMode = .interactive
        scrollView.showsVerticalScrollIndicator = false
        contentStack.axis = .vertical
        contentStack.spacing = AppSpacing.sm

        descriptionView.font = .systemFont(ofSize: 15)
        descriptionView.textColor = AppColor.textPrimary
        descriptionView.backgroundColor = .clear
        descriptionView.textContainerInset = UIEdgeInsets(top: 10, left: 8, bottom: 34, right: 8)
        descriptionView.delegate = self

        contactField.placeholder = "请输入摄影师微信号或手机号（选填）"
        contactField.font = .app(.body)
        contactField.textColor = AppColor.textPrimary
        contactField.backgroundColor = UIColor(hex: 0xFBFCFE)
        contactField.layer.cornerRadius = 10
        contactField.layer.borderWidth = 1
        contactField.layer.borderColor = UIColor(hex: 0xCDD5E1).cgColor
        contactField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 12, height: 1))
        contactField.leftViewMode = .always
        contactField.addTarget(self, action: #selector(contactChanged), for: .editingChanged)

        submitButton.setTitle("提交举报", for: .normal)
        submitButton.titleLabel?.font = .systemFont(ofSize: 22, weight: .bold)
        submitButton.setTitleColor(.white, for: .normal)
        submitButton.backgroundColor = AppColor.primary
        submitButton.layer.cornerRadius = 14
        submitButton.layer.shadowColor = AppColor.primary.cgColor
        submitButton.layer.shadowOpacity = 0.22
        submitButton.layer.shadowRadius = 12
        submitButton.layer.shadowOffset = CGSize(width: 0, height: 6)
        submitButton.addTarget(self, action: #selector(submitTapped), for: .touchUpInside)

        view.addSubview(scrollView)
        scrollView.addSubview(contentStack)
        rebuildContent()
    }

    override func setupConstraints() {
        scrollView.snp.makeConstraints { make in
            make.edges.equalTo(view.safeAreaLayoutGuide)
        }
        contentStack.snp.makeConstraints { make in
            make.edges.equalTo(scrollView.contentLayoutGuide).inset(UIEdgeInsets(top: 14, left: 18, bottom: 26, right: 18))
            make.width.equalTo(scrollView.frameLayoutGuide).offset(-36)
        }
    }

    override func bindActions() {
        viewModel.onStateChange = { [weak self] in
            Task { @MainActor in self?.rebuildContent() }
        }
        viewModel.onShowMessage = { [weak self] message in
            Task { @MainActor in self?.showToast(message) }
        }
        viewModel.onSubmitSuccess = { [weak self] result in
            Task { @MainActor in
                guard let self else { return }
                self.navigationController?.pushViewController(
                    WildPhotographerReportSuccessViewController(
                        result: result,
                        homeViewModel: self.homeViewModel
                    ),
                    animated: true
                )
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        viewModel.loadInitialLocationIfNeeded()
    }

    @MainActor
    private func rebuildContent() {
        contentStack.arrangedSubviews.forEach { view in
            contentStack.removeArrangedSubview(view)
            view.removeFromSuperview()
        }
        contentStack.addArrangedSubview(makeRealNameBanner())
        contentStack.addArrangedSubview(makeTypeCard())
        contentStack.addArrangedSubview(makeEvidenceCard())
        contentStack.addArrangedSubview(makeDescriptionCard())
        contentStack.addArrangedSubview(makeLocationCard())
        contentStack.addArrangedSubview(makeContactCard())
        let paymentCard = makePaymentCard()
        contentStack.addArrangedSubview(paymentCard)
        contentStack.setCustomSpacing(16, after: paymentCard)
        contentStack.addArrangedSubview(submitButton)
        submitButton.snp.remakeConstraints { make in
            make.height.equalTo(56)
        }
    }

    private func makeRealNameBanner() -> UIView {
        let banner = UIView()
        banner.backgroundColor = UIColor(hex: 0xF6FAFF)
        banner.layer.cornerRadius = 16
        banner.layer.borderWidth = 1
        banner.layer.borderColor = UIColor(hex: 0xBFD7FF).cgColor

        let iconWrap = UIView()
        iconWrap.backgroundColor = AppColor.primary.withAlphaComponent(0.10)
        iconWrap.layer.cornerRadius = 17
        let icon = UIImageView(image: UIImage(systemName: "checkmark.shield.fill"))
        icon.tintColor = AppColor.primary
        iconWrap.addSubview(icon)
        icon.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(22)
        }

        let message = UILabel()
        message.numberOfLines = 0
        message.attributedText = realNameBannerText()

        banner.addSubview(iconWrap)
        banner.addSubview(message)
        iconWrap.snp.makeConstraints { make in
            make.top.leading.equalToSuperview().offset(16)
            make.size.equalTo(34)
            make.bottom.lessThanOrEqualToSuperview().inset(16)
        }
        message.snp.makeConstraints { make in
            make.top.trailing.bottom.equalToSuperview().inset(16)
            make.leading.equalTo(iconWrap.snp.trailing).offset(12)
        }
        return banner
    }

    private func makeTypeCard() -> UIView {
        let card = sectionCard(index: 1, title: "举报类型")
        let row = UIStackView()
        row.axis = .horizontal
        row.spacing = 8
        row.distribution = .fillEqually
        WildReportType.allCases.forEach { type in
            let button = WildReportTypeOptionButton()
            button.apply(type: type, isSelected: type == viewModel.selectedReportType)
            button.addAction(UIAction { [weak self] _ in self?.viewModel.selectReportType(type) }, for: .touchUpInside)
            button.snp.makeConstraints { make in make.height.equalTo(72) }
            row.addArrangedSubview(button)
        }
        card.stack.addArrangedSubview(row)
        return card
    }

    private func makeEvidenceCard() -> UIView {
        let card = sectionCard(index: 2, title: "上传现场证据")
        card.stack.addArrangedSubview(makeEvidenceUploadBlock(
            icon: "photo.fill",
            title: "上传图片",
            subtitle: "支持 JPG、PNG 格式，最多 9 张",
            attachments: viewModel.images,
            maxCount: 9,
            kind: .image
        ))
        card.stack.addArrangedSubview(makeDivider())
        card.stack.addArrangedSubview(makeEvidenceUploadBlock(
            icon: "video.fill",
            title: "上传视频",
            subtitle: "支持 MP4 格式，时长不超过 60 秒",
            attachments: viewModel.videos,
            maxCount: 3,
            kind: .video
        ))
        return card
    }

    private func makeDescriptionCard() -> UIView {
        let card = sectionCard(index: 3, title: "举报说明")
        descriptionView.text = viewModel.description
        let inputContainer = UIView()
        inputContainer.backgroundColor = UIColor(hex: 0xFBFCFE)
        inputContainer.layer.cornerRadius = 12
        inputContainer.layer.borderWidth = 1
        inputContainer.layer.borderColor = UIColor(hex: 0xCDD5E1).cgColor

        let placeholder = UILabel()
        placeholder.text = "请描述摄影师的位置、特征、行为..."
        placeholder.font = .systemFont(ofSize: 15)
        placeholder.textColor = UIColor(hex: 0x9CA3AF)
        placeholder.isHidden = !viewModel.description.isEmpty

        let count = WildReportUI.label("\(viewModel.description.count)/500", font: .systemFont(ofSize: 14), color: UIColor(hex: 0x6B7280))
        count.textAlignment = .right

        inputContainer.addSubview(descriptionView)
        inputContainer.addSubview(placeholder)
        inputContainer.addSubview(count)
        descriptionView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
            make.height.equalTo(132)
        }
        placeholder.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(18)
            make.leading.equalToSuperview().offset(14)
            make.trailing.lessThanOrEqualToSuperview().inset(14)
        }
        count.snp.makeConstraints { make in
            make.trailing.bottom.equalToSuperview().inset(12)
        }
        card.stack.addArrangedSubview(inputContainer)
        return card
    }

    private func makeLocationCard() -> UIView {
        let card = sectionCard(index: 4, title: "举报位置")
        let container = UIView()
        container.backgroundColor = UIColor(hex: 0xF6FAFF)
        container.layer.cornerRadius = 12
        container.layer.borderWidth = 1
        container.layer.borderColor = UIColor(hex: 0xC8DDFF).cgColor

        let iconWrap = UIView()
        iconWrap.backgroundColor = AppColor.primary.withAlphaComponent(0.10)
        iconWrap.layer.cornerRadius = 21
        let icon = UIImageView(image: UIImage(systemName: "mappin.circle.fill"))
        icon.tintColor = AppColor.primary
        iconWrap.addSubview(icon)
        icon.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(30)
        }

        let textStack = UIStackView()
        textStack.axis = .vertical
        textStack.spacing = 5
        let title = WildReportUI.label(viewModel.locationTitleText, font: .systemFont(ofSize: 15, weight: .semibold), color: AppColor.textPrimary, lines: 2)
        title.adjustsFontSizeToFitWidth = true
        title.minimumScaleFactor = 0.78
        let subtitle = WildReportUI.label(viewModel.locationSubtitleText, font: .systemFont(ofSize: 12), color: AppColor.textSecondary, lines: 0)
        textStack.addArrangedSubview(title)
        textStack.addArrangedSubview(subtitle)

        let button = UIButton(type: .system)
        button.setTitle(viewModel.isUpdatingLocation ? "定位中" : "更新定位", for: .normal)
        button.titleLabel?.font = .systemFont(ofSize: 13, weight: .semibold)
        button.setTitleColor(AppColor.primary, for: .normal)
        button.backgroundColor = .white
        button.layer.cornerRadius = 17
        button.layer.borderWidth = 1
        button.layer.borderColor = AppColor.primary.cgColor
        button.isEnabled = !viewModel.isUpdatingLocation
        button.alpha = viewModel.isUpdatingLocation ? 0.6 : 1
        button.addTarget(self, action: #selector(refreshLocationTapped), for: .touchUpInside)

        container.addSubview(iconWrap)
        container.addSubview(textStack)
        container.addSubview(button)
        iconWrap.snp.makeConstraints { make in
            make.leading.top.bottom.equalToSuperview().inset(12)
            make.size.equalTo(42)
        }
        button.snp.makeConstraints { make in
            make.trailing.equalToSuperview().inset(12)
            make.centerY.equalToSuperview()
            make.width.equalTo(82)
            make.height.equalTo(34)
        }
        textStack.snp.makeConstraints { make in
            make.leading.equalTo(iconWrap.snp.trailing).offset(12)
            make.trailing.equalTo(button.snp.leading).offset(-8)
            make.centerY.equalToSuperview()
            make.top.greaterThanOrEqualToSuperview().offset(12)
            make.bottom.lessThanOrEqualToSuperview().inset(12)
        }
        card.stack.addArrangedSubview(container)
        return card
    }

    private func makeContactCard() -> UIView {
        let card = sectionCard(index: 5, title: "摄影师微信号/手机号", optional: true)
        contactField.text = viewModel.contact
        card.stack.addArrangedSubview(contactField)
        contactField.snp.makeConstraints { make in make.height.equalTo(48) }
        return card
    }

    private func makePaymentCard() -> UIView {
        let card = sectionCard(index: 6, title: "线下微信/支付宝支付截图", optional: true)
        let row = UIView()
        row.backgroundColor = UIColor(hex: 0xFBFCFE)
        row.layer.cornerRadius = 12
        row.layer.borderWidth = 1
        row.layer.borderColor = UIColor(hex: 0xCDD5E1).cgColor

        let iconWrap = UIView()
        iconWrap.backgroundColor = AppColor.primaryLight
        iconWrap.layer.cornerRadius = 12
        let icon = UIImageView(image: UIImage(systemName: "creditcard.fill"))
        icon.tintColor = AppColor.primary
        iconWrap.addSubview(icon)
        icon.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(24)
        }

        let textStack = UIStackView()
        textStack.axis = .vertical
        textStack.spacing = 4
        textStack.addArrangedSubview(WildReportUI.label("上传线下微信/支付宝支付截图（选填）", font: .systemFont(ofSize: 15, weight: .semibold), color: AppColor.textPrimary, lines: 0))
        textStack.addArrangedSubview(WildReportUI.label("支持 JPG、PNG 格式，最多 3 张", font: .systemFont(ofSize: 12), color: AppColor.textSecondary))

        let trailingView: UIView
        if let first = viewModel.paymentImages.first {
            trailingView = WildReportAttachmentTileView(attachment: first) { [weak self] in
                self?.viewModel.removeAttachment(first)
            }
        } else {
            trailingView = WildReportAddAttachmentTileView { [weak self] in
                self?.viewModel.addPaymentImage()
            }
        }

        row.addSubview(iconWrap)
        row.addSubview(textStack)
        row.addSubview(trailingView)
        iconWrap.snp.makeConstraints { make in
            make.leading.top.bottom.equalToSuperview().inset(12)
            make.size.equalTo(44)
        }
        trailingView.snp.makeConstraints { make in
            make.trailing.equalToSuperview().inset(12)
            make.centerY.equalToSuperview()
            make.size.equalTo(58)
        }
        textStack.snp.makeConstraints { make in
            make.leading.equalTo(iconWrap.snp.trailing).offset(12)
            make.trailing.lessThanOrEqualTo(trailingView.snp.leading).offset(-10)
            make.centerY.equalToSuperview()
            make.top.greaterThanOrEqualToSuperview().offset(12)
            make.bottom.lessThanOrEqualToSuperview().inset(12)
        }
        card.stack.addArrangedSubview(row)
        return card
    }

    private func sectionCard(index: Int, title: String, optional: Bool = false) -> WildReportCardView {
        let card = WildReportCardView(spacing: 18, inset: 16)
        card.layer.cornerRadius = 16
        card.stack.addArrangedSubview(WildReportSectionTitleView(index: index, title: title, optional: optional))
        return card
    }

    private func makeEvidenceUploadBlock(
        icon: String,
        title: String,
        subtitle: String,
        attachments: [WildReportAttachment],
        maxCount: Int,
        kind: WildReportAttachmentKind
    ) -> UIView {
        let block = UIStackView()
        block.axis = .vertical
        block.spacing = 12

        let header = UIStackView()
        header.axis = .horizontal
        header.alignment = .center
        header.spacing = 12

        let iconWrap = UIView()
        iconWrap.backgroundColor = AppColor.primaryLight
        iconWrap.layer.cornerRadius = 12
        let image = UIImageView(image: UIImage(systemName: icon))
        image.tintColor = AppColor.primary
        iconWrap.addSubview(image)
        image.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(22)
        }
        iconWrap.snp.makeConstraints { make in
            make.size.equalTo(42)
        }

        let textStack = UIStackView()
        textStack.axis = .vertical
        textStack.spacing = 3
        textStack.addArrangedSubview(WildReportUI.label(title, font: .systemFont(ofSize: 16, weight: .bold), color: AppColor.textPrimary))
        textStack.addArrangedSubview(WildReportUI.label(subtitle, font: .systemFont(ofSize: 13), color: AppColor.textSecondary, lines: 0))

        header.addArrangedSubview(iconWrap)
        header.addArrangedSubview(textStack)
        header.addArrangedSubview(UIView())
        block.addArrangedSubview(header)

        let scroll = UIScrollView()
        scroll.showsHorizontalScrollIndicator = false
        let tiles = UIStackView()
        tiles.axis = .horizontal
        tiles.spacing = 10
        scroll.addSubview(tiles)
        tiles.snp.makeConstraints { make in
            make.edges.equalTo(scroll.contentLayoutGuide).inset(UIEdgeInsets(top: 2, left: 0, bottom: 2, right: 0))
            make.height.equalTo(scroll.frameLayoutGuide).offset(-4)
        }
        attachments.forEach { attachment in
            tiles.addArrangedSubview(WildReportAttachmentTileView(attachment: attachment) { [weak self] in
                self?.viewModel.removeAttachment(attachment)
            })
        }
        let addCount = max(0, min(3, maxCount - attachments.count))
        for _ in 0..<addCount {
            let addTile = WildReportAddAttachmentTileView { [weak self] in
                switch kind {
                case .image:
                    self?.viewModel.addImage()
                case .video:
                    self?.viewModel.addVideo()
                case .payment:
                    self?.viewModel.addPaymentImage()
                }
            }
            tiles.addArrangedSubview(addTile)
        }
        scroll.snp.makeConstraints { make in
            make.height.equalTo(62)
        }
        block.addArrangedSubview(scroll)
        return block
    }

    private func makeDivider() -> UIView {
        let divider = UIView()
        divider.backgroundColor = AppColor.border
        divider.snp.makeConstraints { make in
            make.height.equalTo(1)
        }
        return divider
    }

    private func realNameBannerText() -> NSAttributedString {
        let text = NSMutableAttributedString()
        [
            ("实名登录", AppColor.primary, UIFont.systemFont(ofSize: 16, weight: .bold)),
            ("后提交，", AppColor.textPrimary, UIFont.systemFont(ofSize: 16, weight: .medium)),
            ("景区公安", AppColor.primary, UIFont.systemFont(ofSize: 16, weight: .bold)),
            ("将接收并处理", AppColor.textPrimary, UIFont.systemFont(ofSize: 16, weight: .medium))
        ].forEach { value, color, font in
            text.append(NSAttributedString(string: value, attributes: [
                .foregroundColor: color,
                .font: font
            ]))
        }
        let paragraph = NSMutableParagraphStyle()
        paragraph.lineSpacing = 4
        text.addAttribute(.paragraphStyle, value: paragraph, range: NSRange(location: 0, length: text.length))
        return text
    }

    @objc private func addImageTapped() { viewModel.addImage() }
    @objc private func addVideoTapped() { viewModel.addVideo() }
    @objc private func addPaymentTapped() { viewModel.addPaymentImage() }
    @objc private func refreshLocationTapped() { viewModel.refreshCurrentLocation() }
    @objc private func submitTapped() { viewModel.submitReport() }
    @objc private func contactChanged() { viewModel.updateContact(contactField.text ?? "") }
}

extension WildPhotographerReportSubmitViewController: UITextViewDelegate {
    func textViewDidChange(_ textView: UITextView) {
        viewModel.updateDescription(textView.text)
    }
}

/// 提交页步骤标题，复刻参考页左侧蓝色竖条与选填标识。
private final class WildReportSectionTitleView: UIView {
    init(index: Int, title: String, optional: Bool) {
        super.init(frame: .zero)
        let bar = UIView()
        bar.backgroundColor = AppColor.primary
        bar.layer.cornerRadius = 2

        let label = UILabel()
        label.font = .systemFont(ofSize: 17, weight: .bold)
        label.textColor = AppColor.textPrimary
        label.text = "\(index). \(title)"

        let optionalLabel = UILabel()
        optionalLabel.font = .systemFont(ofSize: 14)
        optionalLabel.textColor = AppColor.textSecondary
        optionalLabel.text = "（选填）"
        optionalLabel.isHidden = !optional

        addSubview(bar)
        addSubview(label)
        addSubview(optionalLabel)
        bar.snp.makeConstraints { make in
            make.leading.equalToSuperview()
            make.centerY.equalToSuperview()
            make.width.equalTo(4)
            make.height.equalTo(20)
        }
        label.snp.makeConstraints { make in
            make.leading.equalTo(bar.snp.trailing).offset(8)
            make.top.bottom.equalToSuperview()
        }
        optionalLabel.snp.makeConstraints { make in
            make.leading.equalTo(label.snp.trailing)
            make.centerY.equalTo(label)
            make.trailing.lessThanOrEqualToSuperview()
        }
    }

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

/// 提交页举报类型三列选择按钮。
private final class WildReportTypeOptionButton: UIControl {
    private let iconView = UIImageView()
    private let titleLabel = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        layer.cornerRadius = 12
        layer.borderWidth = 1

        let stack = UIStackView()
        stack.axis = .vertical
        stack.alignment = .center
        stack.spacing = 6
        stack.isUserInteractionEnabled = false

        iconView.contentMode = .scaleAspectFit
        titleLabel.font = .systemFont(ofSize: 13, weight: .bold)
        titleLabel.textAlignment = .center
        titleLabel.adjustsFontSizeToFitWidth = true
        titleLabel.minimumScaleFactor = 0.8
        titleLabel.lineBreakMode = .byClipping

        addSubview(stack)
        stack.addArrangedSubview(iconView)
        stack.addArrangedSubview(titleLabel)
        iconView.snp.makeConstraints { make in
            make.size.equalTo(22)
        }
        stack.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.leading.trailing.equalToSuperview().inset(6)
        }
    }

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

    func apply(type: WildReportType, isSelected: Bool) {
        iconView.image = UIImage(systemName: type.iconName)
        titleLabel.text = type.rawValue
        backgroundColor = isSelected ? AppColor.primary : UIColor(hex: 0xF6FAFF)
        layer.borderColor = (isSelected ? AppColor.primary : UIColor(hex: 0xC8DDFF)).cgColor
        iconView.tintColor = isSelected ? .white : AppColor.textPrimary
        titleLabel.textColor = isSelected ? .white : AppColor.textPrimary
    }
}

/// 提交页附件缩略 tile，使用渐变和删除角标模拟本地 Mock 附件。
private final class WildReportAttachmentTileView: UIControl {
    private let gradientLayer = CAGradientLayer()
    private let removeAction: () -> Void

    init(attachment: WildReportAttachment, onRemove: @escaping () -> Void) {
        self.removeAction = onRemove
        super.init(frame: .zero)
        layer.cornerRadius = 10
        clipsToBounds = false

        gradientLayer.cornerRadius = 10
        let colors: [UIColor] = attachment.kind == .video
            ? [UIColor(hex: 0xB7D8FF), UIColor(hex: 0x4C8FEF)]
            : [UIColor(hex: 0xCFE6FF), UIColor(hex: 0x7EB4FF)]
        gradientLayer.colors = colors.map(\.cgColor)
        gradientLayer.startPoint = CGPoint(x: 0, y: 0)
        gradientLayer.endPoint = CGPoint(x: 1, y: 1)
        layer.insertSublayer(gradientLayer, at: 0)

        let icon = UIImageView(image: UIImage(systemName: attachment.kind == .video ? "play.circle.fill" : "mountain.2.fill"))
        icon.tintColor = UIColor.white.withAlphaComponent(0.95)
        icon.contentMode = .scaleAspectFit
        addSubview(icon)
        icon.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(attachment.kind == .video ? 30 : 26)
        }

        let removeButton = UIButton(type: .system)
        removeButton.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal)
        removeButton.tintColor = UIColor(hex: 0x8D93A1)
        removeButton.backgroundColor = .white
        removeButton.layer.cornerRadius = 9
        removeButton.addTarget(self, action: #selector(removeTapped), for: .touchUpInside)
        addSubview(removeButton)
        removeButton.snp.makeConstraints { make in
            make.top.trailing.equalToSuperview().inset(-6)
            make.size.equalTo(18)
        }

        snp.makeConstraints { make in
            make.size.equalTo(58)
        }
    }

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

    override func layoutSubviews() {
        super.layoutSubviews()
        gradientLayer.frame = bounds
    }

    @objc private func removeTapped() {
        removeAction()
    }
}

/// 提交页添加附件 tile，白底虚线加号。
private final class WildReportAddAttachmentTileView: UIControl {
    private let tapAction: () -> Void
    private let borderLayer = CAShapeLayer()

    init(action: @escaping () -> Void) {
        self.tapAction = action
        super.init(frame: .zero)
        backgroundColor = .white
        layer.cornerRadius = 10

        borderLayer.strokeColor = UIColor(hex: 0xCDD5E1).cgColor
        borderLayer.fillColor = UIColor.clear.cgColor
        borderLayer.lineWidth = 1
        borderLayer.lineDashPattern = [5, 4]
        layer.addSublayer(borderLayer)

        let icon = UIImageView(image: UIImage(systemName: "plus"))
        icon.tintColor = UIColor(hex: 0x8D93A1)
        icon.contentMode = .scaleAspectFit
        addSubview(icon)
        icon.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(30)
        }

        addTarget(self, action: #selector(tapped), for: .touchUpInside)
        snp.makeConstraints { make in
            make.size.equalTo(58)
        }
    }

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

    override func layoutSubviews() {
        super.layoutSubviews()
        borderLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: 10).cgPath
    }

    @objc private func tapped() {
        tapAction()
    }
}

/// 举报成功页面，展示编号、上传摘要和处理进度。
final class WildPhotographerReportSuccessViewController: BaseViewController {
    private let viewModel: WildPhotographerReportSuccessViewModel
    private let homeViewModel: WildPhotographerReportHomeViewModel
    private let stack = UIStackView()

    init(result: WildReportSubmitResult, homeViewModel: WildPhotographerReportHomeViewModel) {
        self.viewModel = WildPhotographerReportSuccessViewModel(result: result)
        self.homeViewModel = homeViewModel
        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.pageBackgroundSoft
        stack.axis = .vertical
        stack.spacing = AppSpacing.sm
        view.addSubview(stack)

        let hero = WildReportCardView(spacing: AppSpacing.md)
        hero.stack.alignment = .center
        let icon = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
        icon.tintColor = AppColor.success
        icon.snp.makeConstraints { make in make.size.equalTo(58) }
        hero.stack.addArrangedSubview(icon)
        hero.stack.addArrangedSubview(WildReportUI.label("举报已提交", font: .app(.metric), color: AppColor.textPrimary))
        let desc = WildReportUI.label("景区公安已收到线索，将尽快前往现场核实处理", font: .app(.body), color: AppColor.textSecondary, lines: 0)
        desc.textAlignment = .center
        hero.stack.addArrangedSubview(desc)
        stack.addArrangedSubview(hero)

        let info = WildReportCardView(spacing: AppSpacing.sm)
        info.stack.addArrangedSubview(WildReportInfoRowView(title: "举报编号", value: viewModel.result.record.id))
        info.stack.addArrangedSubview(WildReportInfoRowView(title: "上传材料", value: viewModel.uploadSummary))
        info.stack.addArrangedSubview(WildReportInfoRowView(title: "提交时间", value: viewModel.result.record.submitTime))
        stack.addArrangedSubview(info)

        let progress = WildReportCardView(spacing: AppSpacing.sm)
        progress.stack.addArrangedSubview(WildReportUI.label("处理进度", font: .app(.title), color: AppColor.textPrimary))
        viewModel.progressSteps.enumerated().forEach { index, title in
            progress.stack.addArrangedSubview(WildReportUI.label("\(index + 1). \(title)", font: .app(.body), color: AppColor.textSecondary))
        }
        stack.addArrangedSubview(progress)

        let detailButton = AppButton(title: "查看处理进度")
        detailButton.addTarget(self, action: #selector(detailTapped), for: .touchUpInside)
        let homeButton = AppButton(title: "返回首页", style: .secondary)
        homeButton.addTarget(self, action: #selector(homeTapped), for: .touchUpInside)
        stack.addArrangedSubview(detailButton)
        stack.addArrangedSubview(homeButton)
    }

    override func setupConstraints() {
        stack.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide).offset(AppSpacing.md)
            make.leading.trailing.equalToSuperview().inset(AppSpacing.md)
        }
    }

    @objc private func detailTapped() {
        navigationController?.pushViewController(
            WildPhotographerReportDetailViewController(record: viewModel.result.record, homeViewModel: homeViewModel),
            animated: true
        )
    }

    @objc private func homeTapped() {
        navigationController?.popToViewController(
            navigationController?.viewControllers.first(where: { $0 is WildPhotographerReportHomeViewController }) ?? self,
            animated: true
        )
    }
}
