//
//  PermissionApplyViews.swift
//  suixinkan
//

import SnapKit
import UIKit

/// 权限申请模块视觉常量，严格对应 Android Compose 中的尺寸和颜色。
enum PermissionApplyUITokens {
    static let pageBackground = UIColor(hex: 0xF5F5F5)
    static let selectorBorder = UIColor(hex: 0xE0E3EA)
    static let placeholder = UIColor(hex: 0xB3B8C2)
    static let text = UIColor(hex: 0x111827)
    static let existingBackground = UIColor(hex: 0xF8F9FB)
    static let selectedBackground = UIColor(hex: 0xF4F9FF)
    static let selectedBlue = UIColor(hex: 0x1677FF)
    static let existingGreen = UIColor(hex: 0x52C41A)
    static let existingGreenBackground = UIColor(hex: 0xE6F7E6)
    static let disabledButton = UIColor(hex: 0xE0E0E0)
}

/// 权限申请页顶部“申请平台开通新景区”横幅。
final class PermissionApplyBannerView: UIView {

    var onApplyNewScenic: (() -> Void)?

    private let iconView = UIImageView()
    private let titleLabel = UILabel()
    private let applyButton = UIButton(type: .system)

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = AppColor.warningBackground

        iconView.image = UIImage(named: "permission_open_scenic")
            ?? UIImage(systemName: "building.2.fill")?.withTintColor(AppColor.warning, renderingMode: .alwaysOriginal)
        iconView.contentMode = .scaleAspectFit
        iconView.isAccessibilityElement = false

        titleLabel.text = "没有找到心仪的景区"
        titleLabel.font = .systemFont(ofSize: 14, weight: .medium)
        titleLabel.textColor = AppColor.warning
        titleLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

        var configuration = UIButton.Configuration.plain()
        configuration.title = "申请平台开通新景区"
        configuration.image = UIImage(named: "permission_more_scenic")
            ?? UIImage(systemName: "chevron.right")
        configuration.imagePlacement = .trailing
        configuration.imagePadding = 2
        configuration.contentInsets = .zero
        configuration.baseForegroundColor = AppColor.warning
        configuration.titleTextAttributesTransformer = UIConfigurationTextAttributesTransformer { incoming in
            var outgoing = incoming
            outgoing.font = .systemFont(ofSize: 14, weight: .medium)
            return outgoing
        }
        applyButton.configuration = configuration
        applyButton.accessibilityLabel = "申请平台开通新景区"
        applyButton.addTarget(self, action: #selector(applyTapped), for: .touchUpInside)

        [iconView, titleLabel, applyButton].forEach(addSubview)
        iconView.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(16)
            make.centerY.equalToSuperview()
            make.size.equalTo(20)
        }
        titleLabel.snp.makeConstraints { make in
            make.leading.equalTo(iconView.snp.trailing)
            make.centerY.equalToSuperview()
            make.trailing.lessThanOrEqualTo(applyButton.snp.leading).offset(-12)
        }
        applyButton.snp.makeConstraints { make in
            make.trailing.equalToSuperview().offset(-16)
            make.centerY.equalToSuperview()
            make.height.greaterThanOrEqualTo(44)
        }
        snp.makeConstraints { make in make.height.equalTo(48) }
    }

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

    @objc private func applyTapped() {
        onApplyNewScenic?()
    }
}

/// Android 表单标题、说明和锚定选择框组合视图。
final class PermissionFormSelectorRow: UIView {

    var onTap: (() -> Void)?

    private let titleLabel = UILabel()
    private let tagLabel = UILabel()
    private let descriptionLabel = UILabel()
    let selectorControl = UIControl()
    private let valueLabel = UILabel()
    private let chevron = UIImageView(image: UIImage(systemName: "chevron.down"))

    init(title: String, tag: String, description: String, placeholder: String) {
        super.init(frame: .zero)
        titleLabel.text = title
        titleLabel.font = .systemFont(ofSize: 16, weight: .medium)
        titleLabel.textColor = UIColor(hex: 0x333333)

        tagLabel.text = tag
        tagLabel.font = .systemFont(ofSize: 12)
        tagLabel.textColor = AppColor.textTertiary
        tagLabel.textAlignment = .right

        descriptionLabel.text = description
        descriptionLabel.font = .systemFont(ofSize: 12)
        descriptionLabel.textColor = PermissionApplyUITokens.placeholder
        descriptionLabel.numberOfLines = 0

        selectorControl.backgroundColor = .white
        selectorControl.layer.cornerRadius = 12
        selectorControl.layer.borderWidth = 1
        selectorControl.layer.borderColor = PermissionApplyUITokens.selectorBorder.cgColor
        selectorControl.accessibilityLabel = title
        selectorControl.addTarget(self, action: #selector(rowTapped), for: .touchUpInside)

        valueLabel.text = placeholder
        valueLabel.font = .systemFont(ofSize: 14)
        valueLabel.textColor = PermissionApplyUITokens.placeholder
        valueLabel.lineBreakMode = .byTruncatingTail

        chevron.tintColor = PermissionApplyUITokens.placeholder
        chevron.contentMode = .scaleAspectFit

        [titleLabel, tagLabel, descriptionLabel, selectorControl].forEach(addSubview)
        [valueLabel, chevron].forEach(selectorControl.addSubview)

        titleLabel.snp.makeConstraints { make in make.top.leading.equalToSuperview() }
        tagLabel.snp.makeConstraints { make in
            make.centerY.equalTo(titleLabel)
            make.trailing.equalToSuperview()
            make.leading.greaterThanOrEqualTo(titleLabel.snp.trailing).offset(8)
        }
        descriptionLabel.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(4)
            make.leading.trailing.equalToSuperview()
        }
        selectorControl.snp.makeConstraints { make in
            make.top.equalTo(descriptionLabel.snp.bottom).offset(8)
            make.leading.trailing.bottom.equalToSuperview()
            make.height.equalTo(46)
        }
        valueLabel.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(16)
            make.centerY.equalToSuperview()
            make.trailing.lessThanOrEqualTo(chevron.snp.leading).offset(-8)
        }
        chevron.snp.makeConstraints { make in
            make.trailing.equalToSuperview().offset(-16)
            make.centerY.equalToSuperview()
            make.size.equalTo(20)
        }
    }

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

    /// 更新选择框显示值。
    func setValue(_ text: String, isPlaceholder: Bool) {
        valueLabel.text = text
        valueLabel.textColor = isPlaceholder ? PermissionApplyUITokens.placeholder : PermissionApplyUITokens.text
        selectorControl.accessibilityValue = text
    }

    @objc private func rowTapped() {
        onTap?()
    }
}

/// 权限标签的展示样式。
enum PermissionChipStyle: Hashable {
    case selectedRemovable
    case selectedStatic
    case existingGreen
}

/// Diffable 标签网格中的稳定条目。
struct PermissionChipItem: Hashable {
    let id: String
    let title: String
}

/// Android `FlowRow` 的标签左对齐与换行坐标计算器。
struct PermissionChipLayoutMetrics {
    static let itemHeight: CGFloat = 44
    static let interitemSpacing: CGFloat = 12
    static let lineSpacing: CGFloat = 2

    /// 按容器宽度为标签生成从左到右、超宽换行的坐标。
    static func makeFrames(itemWidths: [CGFloat], containerWidth: CGFloat) -> [CGRect] {
        guard containerWidth > 0 else { return [] }
        var x: CGFloat = 0
        var y: CGFloat = 0
        return itemWidths.map { rawWidth in
            let width = min(containerWidth, max(44, rawWidth))
            if x > 0, x + width > containerWidth + 0.5 {
                x = 0
                y += itemHeight + lineSpacing
            }
            let frame = CGRect(x: x, y: y, width: width, height: itemHeight)
            x += width + interitemSpacing
            return frame
        }
    }
}

/// 确定性计算左对齐换行坐标，等价于 Android `FlowRow`。
private final class PermissionChipFlowLayout: UICollectionViewLayout {

    var itemWidthProvider: ((IndexPath) -> CGFloat)?
    private var cachedAttributes: [IndexPath: UICollectionViewLayoutAttributes] = [:]
    private var contentHeight: CGFloat = 1

    override func prepare() {
        super.prepare()
        guard let collectionView, collectionView.bounds.width > 0 else {
            cachedAttributes = [:]
            contentHeight = 1
            return
        }

        cachedAttributes = [:]
        let availableWidth = collectionView.bounds.width
        var indexPaths: [IndexPath] = []
        var itemWidths: [CGFloat] = []
        for section in 0..<collectionView.numberOfSections {
            for item in 0..<collectionView.numberOfItems(inSection: section) {
                let indexPath = IndexPath(item: item, section: section)
                indexPaths.append(indexPath)
                itemWidths.append(itemWidthProvider?(indexPath) ?? 44)
            }
        }
        let frames = PermissionChipLayoutMetrics.makeFrames(
            itemWidths: itemWidths,
            containerWidth: availableWidth
        )
        for (index, indexPath) in indexPaths.enumerated() {
            let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            attributes.frame = frames[index]
            cachedAttributes[indexPath] = attributes
        }
        contentHeight = frames.last?.maxY ?? 1
    }

    override var collectionViewContentSize: CGSize {
        CGSize(width: collectionView?.bounds.width ?? 0, height: contentHeight)
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        cachedAttributes.values.filter { $0.frame.intersects(rect) }
    }

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        cachedAttributes[indexPath]
    }

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        guard let collectionView else { return true }
        return abs(collectionView.bounds.width - newBounds.width) > 0.5
    }
}

/// 自适应换行的权限标签网格。
final class PermissionChipCollectionView: UIView {

    private enum Section { case main }

    var onRemove: ((Int) -> Void)?

    private let style: PermissionChipStyle
    private let layout: PermissionChipFlowLayout
    private let collectionView: UICollectionView
    private var dataSource: UICollectionViewDiffableDataSource<Section, PermissionChipItem>!
    private var items: [PermissionChipItem] = []
    private var heightConstraint: Constraint?

    init(style: PermissionChipStyle) {
        self.style = style
        let layout = PermissionChipFlowLayout()
        self.layout = layout
        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        super.init(frame: .zero)

        collectionView.backgroundColor = .clear
        collectionView.isScrollEnabled = false
        collectionView.register(PermissionChipCell.self, forCellWithReuseIdentifier: PermissionChipCell.reuseIdentifier)
        addSubview(collectionView)
        collectionView.snp.makeConstraints { make in make.edges.equalToSuperview() }
        snp.makeConstraints { make in heightConstraint = make.height.equalTo(1).constraint }

        dataSource = UICollectionViewDiffableDataSource<Section, PermissionChipItem>(
            collectionView: collectionView
        ) { [weak self] collectionView, indexPath, item in
            guard let self,
                  let cell = collectionView.dequeueReusableCell(
                    withReuseIdentifier: PermissionChipCell.reuseIdentifier,
                    for: indexPath
                  ) as? PermissionChipCell else { return UICollectionViewCell() }
            cell.apply(title: item.title, style: self.style)
            cell.onRemove = { [weak self] in
                guard let self, let currentIndex = self.items.firstIndex(of: item) else { return }
                self.onRemove?(currentIndex)
            }
            return cell
        }
        layout.itemWidthProvider = { [weak self] indexPath in
            self?.itemWidth(at: indexPath) ?? 44
        }
    }

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

    /// 使用 Diffable snapshot 更新标签。
    func apply(titles: [String]) {
        var occurrences: [String: Int] = [:]
        items = titles.map { title in
            let occurrence = occurrences[title, default: 0]
            occurrences[title] = occurrence + 1
            return PermissionChipItem(id: "\(title)#\(occurrence)", title: title)
        }
        var snapshot = NSDiffableDataSourceSnapshot<Section, PermissionChipItem>()
        snapshot.appendSections([.main])
        snapshot.appendItems(items)
        dataSource.apply(snapshot, animatingDifferences: true) { [weak self] in
            self?.updateHeight()
        }
    }

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

    private func updateHeight() {
        collectionView.collectionViewLayout.invalidateLayout()
        collectionView.layoutIfNeeded()
        let height = max(1, collectionView.collectionViewLayout.collectionViewContentSize.height)
        heightConstraint?.update(offset: height)
        invalidateIntrinsicContentSize()
    }

    private func itemWidth(at indexPath: IndexPath) -> CGFloat {
        guard let item = dataSource.itemIdentifier(for: indexPath) else { return 44 }
        let textWidth = ceil((item.title as NSString).size(withAttributes: [
            .font: UIFont.systemFont(ofSize: 14),
        ]).width)
        let horizontalChrome: CGFloat = style == .selectedRemovable ? 42 : 24
        return textWidth + horizontalChrome
    }
}

/// 带标题背景的“新增角色/新增景区”区域。
final class PermissionSelectedTagsView: UIView {

    private let titleLabel = UILabel()
    private let chips = PermissionChipCollectionView(style: .selectedRemovable)

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = PermissionApplyUITokens.selectedBackground
        layer.cornerRadius = 12
        titleLabel.font = .systemFont(ofSize: 16, weight: .medium)
        titleLabel.textColor = PermissionApplyUITokens.text

        addSubview(titleLabel)
        addSubview(chips)
        titleLabel.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview().inset(12)
        }
        chips.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(12)
            make.leading.trailing.bottom.equalToSuperview().inset(12)
        }
    }

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

    /// 更新区域标题与标签内容。
    func apply(title: String, names: [String], onRemove: ((Int) -> Void)? = nil) {
        titleLabel.text = title
        isHidden = names.isEmpty
        chips.onRemove = onRemove
        chips.apply(titles: names)
    }
}

/// 权限申请页底部主按钮。
final class PermissionSubmitButton: UIButton {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setTitle("提交审核", for: .normal)
        setTitleColor(.white, for: .normal)
        titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
        layer.cornerRadius = 8
        accessibilityLabel = "提交审核"
        snp.makeConstraints { make in make.height.equalTo(48) }
        applyState(canSubmit: false, submitting: false)
    }

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

    /// 更新可提交与提交中状态。
    func applyState(canSubmit: Bool, submitting: Bool) {
        isEnabled = canSubmit && !submitting
        backgroundColor = isEnabled ? PermissionApplyUITokens.selectedBlue : PermissionApplyUITokens.disabledButton
        setTitle(submitting ? "提交中..." : "提交审核", for: .normal)
        accessibilityValue = submitting ? "提交中" : nil
    }
}

/// 权限标签 CollectionView 单元格。
private final class PermissionChipCell: UICollectionViewCell {

    static let reuseIdentifier = "PermissionChipCell"

    var onRemove: (() -> Void)?

    private let chipBackground = UIView()
    private let label = UILabel()
    private let removeButton = UIButton(type: .system)
    private let removeImageView = UIImageView(image: UIImage(systemName: "xmark"))

    override init(frame: CGRect) {
        super.init(frame: frame)
        label.font = .systemFont(ofSize: 14)
        label.lineBreakMode = .byTruncatingTail
        removeButton.addTarget(self, action: #selector(removeTapped), for: .touchUpInside)
        removeButton.accessibilityLabel = "删除"
        removeImageView.contentMode = .scaleAspectFit
        removeImageView.isUserInteractionEnabled = false
        contentView.addSubview(chipBackground)
        chipBackground.addSubview(label)
        chipBackground.addSubview(removeImageView)
        contentView.addSubview(removeButton)

        chipBackground.snp.makeConstraints { make in
            make.leading.trailing.centerY.equalToSuperview()
            make.height.equalTo(34)
        }
        removeButton.snp.makeConstraints { make in
            make.trailing.centerY.equalToSuperview()
            make.size.equalTo(44)
        }
        removeImageView.snp.makeConstraints { make in
            make.trailing.equalToSuperview().offset(-10)
            make.centerY.equalToSuperview()
            make.size.equalTo(14)
        }
    }

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

    func apply(title: String, style: PermissionChipStyle) {
        label.text = title
        chipBackground.layer.cornerRadius = style == .existingGreen ? 4 : 8
        chipBackground.layer.borderWidth = 1
        switch style {
        case .selectedRemovable, .selectedStatic:
            chipBackground.backgroundColor = style == .selectedRemovable
                ? PermissionApplyUITokens.selectedBackground : .white
            chipBackground.layer.borderColor = PermissionApplyUITokens.selectedBlue.cgColor
            label.textColor = PermissionApplyUITokens.selectedBlue
            removeImageView.tintColor = PermissionApplyUITokens.selectedBlue
        case .existingGreen:
            chipBackground.backgroundColor = PermissionApplyUITokens.existingGreenBackground
            chipBackground.layer.borderColor = PermissionApplyUITokens.existingGreen.cgColor
            label.textColor = PermissionApplyUITokens.existingGreen
            removeImageView.tintColor = PermissionApplyUITokens.existingGreen
        }
        let removable = style == .selectedRemovable
        removeButton.isHidden = !removable
        removeImageView.isHidden = !removable
        label.snp.remakeConstraints { make in
            make.leading.equalToSuperview().offset(12)
            make.centerY.equalToSuperview()
            if removable {
                make.trailing.equalTo(removeImageView.snp.leading).offset(-6)
            } else {
                make.trailing.equalToSuperview().offset(-12)
            }
        }
        accessibilityLabel = title
    }

    @objc private func removeTapped() {
        onRemove?()
    }
}
