//
//  PermissionRoleViews.swift
//  suixinkan
//

import SnapKit
import UIKit

/// “已有角色信息”中的稳定可展开条目。
private struct PermissionExistingRoleItem: Hashable {
    let id: String
    let roleName: String
    let scenics: [ScenicInfo]
    var isExpanded: Bool
}

/// Android 风格“已有角色信息”折叠列表。
final class PermissionExistingRoleListView: UIView, UITableViewDelegate {

    private enum Section { case main }

    var onShowAllScenics: ((String, [ScenicInfo]) -> Void)?

    private let titleLabel = UILabel()
    private let tableView = UITableView(frame: .zero, style: .plain)
    private var dataSource: UITableViewDiffableDataSource<Section, String>!
    private var items: [PermissionExistingRoleItem] = []
    private var tableHeightConstraint: Constraint?

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = PermissionApplyUITokens.existingBackground
        layer.cornerRadius = 12
        titleLabel.text = "已有角色信息"
        titleLabel.font = .systemFont(ofSize: 16, weight: .medium)
        titleLabel.textColor = PermissionApplyUITokens.text

        tableView.backgroundColor = .clear
        tableView.separatorStyle = .none
        tableView.isScrollEnabled = false
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 52
        tableView.delegate = self
        tableView.register(PermissionExistingRoleCell.self, forCellReuseIdentifier: PermissionExistingRoleCell.reuseIdentifier)

        addSubview(titleLabel)
        addSubview(tableView)
        titleLabel.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview().inset(12)
        }
        tableView.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(12)
            make.leading.trailing.bottom.equalToSuperview().inset(12)
            tableHeightConstraint = make.height.equalTo(1).constraint
        }

        dataSource = UITableViewDiffableDataSource<Section, String>(tableView: tableView) {
            [weak self] tableView, indexPath, itemID in
            guard let self,
                  let item = self.items.first(where: { $0.id == itemID }),
                  let cell = tableView.dequeueReusableCell(
                    withIdentifier: PermissionExistingRoleCell.reuseIdentifier,
                    for: indexPath
                  ) as? PermissionExistingRoleCell else { return UITableViewCell() }
            cell.apply(item: item)
            cell.onToggle = { [weak self] in self?.toggle(itemID: item.id) }
            cell.onShowAll = { [weak self] in self?.onShowAllScenics?(item.roleName, item.scenics) }
            return cell
        }
    }

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

    /// 使用本地权限缓存构建已有角色列表。
    func apply(rolePermissions: [RolePermissionResponse]) {
        let expandedIDs = Set(items.filter(\.isExpanded).map(\.id))
        items = rolePermissions.enumerated().map { index, value in
            let id = "\(index)-\(value.role.id)-\(value.role.name)"
            return PermissionExistingRoleItem(
                id: id,
                roleName: value.role.name,
                scenics: value.scenic,
                isExpanded: expandedIDs.contains(id)
            )
        }
        isHidden = items.isEmpty
        applySnapshot(animatingExpansion: false, reconfigureExisting: true)
    }

    private func toggle(itemID: String) {
        guard let index = items.firstIndex(where: { $0.id == itemID }) else { return }
        items[index].isExpanded.toggle()
        if let indexPath = dataSource.indexPath(for: itemID),
           let cell = tableView.cellForRow(at: indexPath) as? PermissionExistingRoleCell {
            cell.apply(item: items[index], animated: true)
        }
        applySnapshot(animatingExpansion: true, reconfigureExisting: false)
    }

    private func applySnapshot(animatingExpansion: Bool, reconfigureExisting: Bool) {
        var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
        snapshot.appendSections([.main])
        let itemIDs = items.map(\.id)
        snapshot.appendItems(itemIDs)
        if reconfigureExisting {
            let currentIDs = Set(dataSource.snapshot().itemIdentifiers)
            snapshot.reconfigureItems(itemIDs.filter(currentIDs.contains))
        }
        dataSource.apply(snapshot, animatingDifferences: false) { [weak self] in
            self?.updateHeight(animated: animatingExpansion)
        }
    }

    private func updateHeight(animated: Bool) {
        let layoutRoot = superview ?? self
        layoutRoot.layoutIfNeeded()
        let updates = { [self] in
            tableView.beginUpdates()
            tableView.endUpdates()
            tableView.layoutIfNeeded()
            tableHeightConstraint?.update(offset: max(1, tableView.contentSize.height))
            invalidateIntrinsicContentSize()
            layoutRoot.layoutIfNeeded()
        }
        guard animated, !UIAccessibility.isReduceMotionEnabled else {
            UIView.performWithoutAnimation(updates)
            return
        }
        UIView.animate(
            withDuration: 0.24,
            delay: 0,
            options: [.curveEaseOut, .beginFromCurrentState, .allowUserInteraction],
            animations: updates
        )
    }
}

/// 已有角色折叠列表单元格。
private final class PermissionExistingRoleCell: UITableViewCell {

    static let reuseIdentifier = "PermissionExistingRoleCell"

    var onToggle: (() -> Void)?
    var onShowAll: (() -> Void)?

    private let cardView = UIView()
    private let headerControl = UIControl()
    private let titleLabel = UILabel()
    private let chevron = UIImageView()
    private let expandedContainer = UIView()
    private let flowView = PermissionSimpleFlowView()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        backgroundColor = .clear
        selectionStyle = .none
        contentView.backgroundColor = .clear
        cardView.backgroundColor = .white
        cardView.layer.cornerRadius = 8
        cardView.layer.shadowColor = UIColor.black.cgColor
        cardView.layer.shadowOpacity = 0.08
        cardView.layer.shadowRadius = 1
        cardView.layer.shadowOffset = CGSize(width: 0, height: 1)

        titleLabel.font = .systemFont(ofSize: 14, weight: .medium)
        titleLabel.textColor = PermissionApplyUITokens.text
        chevron.image = UIImage(systemName: "chevron.down")
        chevron.tintColor = AppColor.textTertiary
        chevron.contentMode = .scaleAspectFit
        headerControl.addTarget(self, action: #selector(toggleTapped), for: .touchUpInside)
        expandedContainer.backgroundColor = PermissionApplyUITokens.existingBackground
        flowView.onMore = { [weak self] in self?.onShowAll?() }

        contentView.addSubview(cardView)
        cardView.addSubview(headerControl)
        headerControl.addSubview(titleLabel)
        headerControl.addSubview(chevron)
        cardView.addSubview(expandedContainer)
        expandedContainer.addSubview(flowView)

        cardView.snp.makeConstraints { make in
            make.top.equalToSuperview()
            make.leading.trailing.equalToSuperview()
            make.bottom.equalToSuperview().offset(-8)
        }
        headerControl.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview()
            make.height.equalTo(44)
        }
        titleLabel.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)
        }
        expandedContainer.snp.makeConstraints { make in
            make.top.equalTo(headerControl.snp.bottom)
            make.leading.trailing.bottom.equalToSuperview()
        }
        flowView.snp.makeConstraints { make in make.edges.equalToSuperview().inset(12) }
    }

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

    func apply(item: PermissionExistingRoleItem, animated: Bool = false) {
        titleLabel.text = item.roleName
        headerControl.accessibilityLabel = item.roleName
        headerControl.accessibilityValue = item.isExpanded ? "已展开" : "已收起"
        flowView.apply(titles: item.scenics.map(\.name), showsMore: item.scenics.count > 3)
        let showsExpandedContent = item.isExpanded && !item.scenics.isEmpty
        let isExpanding = expandedContainer.isHidden && showsExpandedContent
        expandedContainer.isHidden = !showsExpandedContent

        let updates = { [self] in
            chevron.transform = item.isExpanded
                ? CGAffineTransform(rotationAngle: .pi)
                : .identity
            expandedContainer.alpha = 1
            expandedContainer.transform = .identity
        }
        guard animated, !UIAccessibility.isReduceMotionEnabled else {
            UIView.performWithoutAnimation(updates)
            return
        }
        if isExpanding {
            expandedContainer.alpha = 0
            expandedContainer.transform = CGAffineTransform(translationX: 0, y: -8)
        }
        UIView.animate(
            withDuration: 0.24,
            delay: 0,
            options: [.curveEaseOut, .beginFromCurrentState, .allowUserInteraction],
            animations: updates
        )
    }

    @objc private func toggleTapped() {
        onToggle?()
    }
}

/// 小规模绿色景区标签的手动换行容器。
private final class PermissionSimpleFlowView: UIView {

    var onMore: (() -> Void)?

    private var itemViews: [UIView] = []
    private var lastLayoutWidth: CGFloat = 0

    func apply(titles: [String], showsMore: Bool) {
        itemViews.forEach { $0.removeFromSuperview() }
        itemViews = []
        var values = Array(titles.prefix(3))
        if showsMore { values.append("···") }
        for value in values {
            let button = UIButton(type: .system)
            button.setTitle(value, for: .normal)
            button.setTitleColor(PermissionApplyUITokens.existingGreen, for: .normal)
            button.titleLabel?.font = .systemFont(ofSize: 14)
            button.setConfigurationContentInsets(
                NSDirectionalEdgeInsets(top: 8, leading: 12, bottom: 8, trailing: 12)
            )
            button.backgroundColor = PermissionApplyUITokens.existingGreenBackground
            button.layer.cornerRadius = 4
            button.layer.borderWidth = 1
            button.layer.borderColor = PermissionApplyUITokens.existingGreen.cgColor
            button.isUserInteractionEnabled = value == "···"
            if value == "···" {
                button.addTarget(self, action: #selector(moreTapped), for: .touchUpInside)
                button.accessibilityLabel = "查看全部景区"
            }
            addSubview(button)
            itemViews.append(button)
        }
        setNeedsLayout()
        invalidateIntrinsicContentSize()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        guard bounds.width > 0 else { return }
        let widthChanged = abs(bounds.width - lastLayoutWidth) > 0.5
        lastLayoutWidth = bounds.width
        var x: CGFloat = 0
        var y: CGFloat = 0
        var rowHeight: CGFloat = 0
        for view in itemViews {
            let fitted = view.sizeThatFits(CGSize(width: min(180, bounds.width), height: 34))
            let width = min(bounds.width, max(42, fitted.width))
            let height = max(34, fitted.height)
            if x > 0, x + width > bounds.width {
                x = 0
                y += rowHeight + 12
                rowHeight = 0
            }
            view.frame = CGRect(x: x, y: y, width: width, height: height)
            x += width + 12
            rowHeight = max(rowHeight, height)
        }
        if widthChanged { invalidateIntrinsicContentSize() }
    }

    override var intrinsicContentSize: CGSize {
        let width = bounds.width > 0 ? bounds.width : 280
        var x: CGFloat = 0
        var totalHeight: CGFloat = 0
        var rowHeight: CGFloat = 0
        for view in itemViews {
            let fitted = view.sizeThatFits(CGSize(width: min(180, width), height: 34))
            let itemWidth = min(width, max(42, fitted.width))
            let itemHeight = max(34, fitted.height)
            if x > 0, x + itemWidth > width {
                totalHeight += rowHeight + 12
                x = 0
                rowHeight = 0
            }
            x += itemWidth + 12
            rowHeight = max(rowHeight, itemHeight)
        }
        return CGSize(width: UIView.noIntrinsicMetric, height: itemViews.isEmpty ? 0 : totalHeight + rowHeight)
    }

    @objc private func moreTapped() {
        onMore?()
    }
}

/// 审核页“新增角色/新增景区”白色卡片。
final class PermissionStaticSectionView: UIView {

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

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        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(16)
        }
        chips.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(12)
            make.leading.trailing.bottom.equalToSuperview().inset(16)
        }
    }

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

    /// 更新标题和不可删除的蓝色标签。
    func apply(title: String, names: [String]) {
        titleLabel.text = title
        chips.apply(titles: names)
    }
}

/// Android 风格角色或景区删除确认弹窗。
final class PermissionDeleteDialogViewController: UIViewController {

    private let target: PermissionDeletionTarget
    private let onCancel: () -> Void
    private let onConfirm: () -> Void

    /// 创建删除确认弹窗。
    init(target: PermissionDeletionTarget, onCancel: @escaping () -> Void, onConfirm: @escaping () -> Void) {
        self.target = target
        self.onCancel = onCancel
        self.onConfirm = onConfirm
        super.init(nibName: nil, bundle: nil)
        modalPresentationStyle = .overFullScreen
        modalTransitionStyle = .crossDissolve
    }

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

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.black.withAlphaComponent(0.32)
        let card = UIView()
        card.backgroundColor = .white
        card.layer.cornerRadius = 16

        let titleLabel = UILabel()
        titleLabel.text = target.dialogTitle
        titleLabel.font = .systemFont(ofSize: 18, weight: .bold)
        titleLabel.textColor = UIColor(hex: 0xFF0000)

        let messageLabel = UILabel()
        messageLabel.numberOfLines = 0
        let message = NSMutableAttributedString(
            string: target.dialogMessage,
            attributes: [.font: UIFont.systemFont(ofSize: 16), .foregroundColor: UIColor(hex: 0x333333)]
        )
        let name: String
        switch target {
        case .role(let value), .scenic(_, let value): name = value
        }
        let range = (target.dialogMessage as NSString).range(of: name)
        if range.location != NSNotFound {
            message.addAttribute(.font, value: UIFont.systemFont(ofSize: 16, weight: .bold), range: range)
        }
        messageLabel.attributedText = message

        let cancel = makeButton(title: "取消", background: UIColor(hex: 0xFFE5E5))
        let confirm = makeButton(title: "确认", background: UIColor(hex: 0xFF0000))
        cancel.addTarget(self, action: #selector(cancelTapped), for: .touchUpInside)
        confirm.addTarget(self, action: #selector(confirmTapped), for: .touchUpInside)
        let buttons = UIStackView(arrangedSubviews: [cancel, confirm])
        buttons.axis = .horizontal
        buttons.spacing = 12
        buttons.distribution = .fillEqually
        buttons.snp.makeConstraints { make in make.height.equalTo(44) }

        let stack = UIStackView(arrangedSubviews: [titleLabel, messageLabel, buttons])
        stack.axis = .vertical
        stack.spacing = 16
        stack.setCustomSpacing(24, after: messageLabel)
        view.addSubview(card)
        card.addSubview(stack)
        card.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.leading.trailing.equalToSuperview().inset(32)
        }
        stack.snp.makeConstraints { make in make.edges.equalToSuperview().inset(24) }
    }

    private func makeButton(title: String, background: UIColor) -> UIButton {
        let button = UIButton(type: .system)
        button.setTitle(title, for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
        button.backgroundColor = background
        button.layer.cornerRadius = 8
        button.accessibilityLabel = title
        return button
    }

    @objc private func cancelTapped() {
        dismiss(animated: true) { [onCancel] in onCancel() }
    }

    @objc private func confirmTapped() {
        dismiss(animated: true) { [onConfirm] in onConfirm() }
    }
}

/// 某个已有角色的全部景区弹窗。
final class PermissionScenicListDialogViewController: UIViewController {

    private enum Section { case main }

    private let roleName: String
    private let scenics: [ScenicInfo]
    private let onDismiss: () -> Void
    private let tableView = UITableView(frame: .zero, style: .plain)
    private var dataSource: UITableViewDiffableDataSource<Section, ScenicInfo>!

    /// 创建固定400pt列表高度的景区详情弹窗。
    init(roleName: String, scenics: [ScenicInfo], onDismiss: @escaping () -> Void) {
        self.roleName = roleName
        self.scenics = scenics
        self.onDismiss = onDismiss
        super.init(nibName: nil, bundle: nil)
        modalPresentationStyle = .overFullScreen
        modalTransitionStyle = .crossDissolve
    }

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

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.black.withAlphaComponent(0.32)
        let card = UIView()
        card.backgroundColor = .white
        card.layer.cornerRadius = 16

        let titleLabel = UILabel()
        titleLabel.text = roleName
        titleLabel.font = .systemFont(ofSize: 18, weight: .bold)
        titleLabel.textColor = UIColor(hex: 0x333333)
        let closeButton = UIButton(type: .system)
        closeButton.setImage(UIImage(systemName: "xmark"), for: .normal)
        closeButton.tintColor = AppColor.textSecondary
        closeButton.accessibilityLabel = "关闭"
        closeButton.addTarget(self, action: #selector(closeTapped), for: .touchUpInside)

        tableView.separatorStyle = .none
        tableView.backgroundColor = .white
        tableView.rowHeight = 50
        tableView.register(PermissionScenicDialogCell.self, forCellReuseIdentifier: PermissionScenicDialogCell.reuseIdentifier)
        dataSource = UITableViewDiffableDataSource<Section, ScenicInfo>(tableView: tableView) {
            tableView, indexPath, scenic in
            guard let cell = tableView.dequeueReusableCell(
                withIdentifier: PermissionScenicDialogCell.reuseIdentifier,
                for: indexPath
            ) as? PermissionScenicDialogCell else { return UITableViewCell() }
            cell.apply(name: scenic.name)
            return cell
        }

        view.addSubview(card)
        [titleLabel, closeButton, tableView].forEach(card.addSubview)
        card.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.leading.trailing.equalToSuperview().inset(32)
        }
        titleLabel.snp.makeConstraints { make in
            make.top.leading.equalToSuperview().inset(24)
            make.trailing.lessThanOrEqualTo(closeButton.snp.leading).offset(-8)
            make.centerY.equalTo(closeButton)
        }
        closeButton.snp.makeConstraints { make in
            make.top.trailing.equalToSuperview().inset(16)
            make.size.equalTo(44)
        }
        tableView.snp.makeConstraints { make in
            make.top.equalTo(closeButton.snp.bottom).offset(8)
            make.leading.trailing.bottom.equalToSuperview().inset(24)
            make.height.equalTo(400)
        }

        var snapshot = NSDiffableDataSourceSnapshot<Section, ScenicInfo>()
        snapshot.appendSections([.main])
        snapshot.appendItems(scenics)
        dataSource.apply(snapshot, animatingDifferences: false)
    }

    @objc private func closeTapped() {
        dismiss(animated: true) { [onDismiss] in onDismiss() }
    }
}

/// 景区详情弹窗中的绿色标签行。
private final class PermissionScenicDialogCell: UITableViewCell {

    static let reuseIdentifier = "PermissionScenicDialogCell"
    private let chipLabel = UILabel()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        selectionStyle = .none
        chipLabel.font = .systemFont(ofSize: 14)
        chipLabel.textColor = PermissionApplyUITokens.existingGreen
        chipLabel.backgroundColor = PermissionApplyUITokens.existingGreenBackground
        chipLabel.layer.cornerRadius = 4
        chipLabel.layer.borderWidth = 1
        chipLabel.layer.borderColor = PermissionApplyUITokens.existingGreen.cgColor
        chipLabel.clipsToBounds = true
        chipLabel.textAlignment = .center
        contentView.addSubview(chipLabel)
        chipLabel.snp.makeConstraints { make in
            make.leading.equalToSuperview()
            make.centerY.equalToSuperview()
            make.height.equalTo(34)
            make.trailing.lessThanOrEqualToSuperview()
        }
    }

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

    func apply(name: String) {
        chipLabel.text = "  \(name)  "
        chipLabel.accessibilityLabel = name
    }
}
