import SwiftUI
import UIKit

// MARK: - RequestChatsController (UIKit)

/// Pure UIKit UICollectionView controller for request chats list.
/// Single flat section with ChatListCell — same rendering as main chat list.
final class RequestChatsController: UIViewController {

    var onSelectDialog: ((Dialog) -> Void)?
    var onDeleteDialog: ((Dialog) -> Void)?

    private var dialogs: [Dialog] = []
    private var isSyncing: Bool = false
    private var dialogMap: [String: Dialog] = [:]

    private var collectionView: UICollectionView!
    private var dataSource: UICollectionViewDiffableDataSource<Int, String>!
    private var cellRegistration: UICollectionView.CellRegistration<ChatListCell, Dialog>!

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor(RosettaColors.Adaptive.background)
        setupCollectionView()
        setupCellRegistration()
        setupDataSource()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        applyBottomInsets()
    }

    override func viewSafeAreaInsetsDidChange() {
        super.viewSafeAreaInsetsDidChange()
        applyBottomInsets()
    }

    // MARK: - Collection View

    private func setupCollectionView() {
        var listConfig = UICollectionLayoutListConfiguration(appearance: .plain)
        listConfig.showsSeparators = false
        listConfig.backgroundColor = .clear
        listConfig.trailingSwipeActionsConfigurationProvider = { [weak self] indexPath in
            self?.trailingSwipeActions(for: indexPath)
        }

        let layout = UICollectionViewCompositionalLayout.list(using: listConfig)

        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.backgroundColor = UIColor(RosettaColors.Adaptive.background)
        collectionView.delegate = self
        collectionView.showsHorizontalScrollIndicator = false
        collectionView.showsVerticalScrollIndicator = false
        collectionView.alwaysBounceHorizontal = false
        collectionView.alwaysBounceVertical = true
        collectionView.contentInsetAdjustmentBehavior = .never
        applyBottomInsets()
        view.addSubview(collectionView)

        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: view.topAnchor),
            collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        ])
    }

    private func applyBottomInsets() {
        guard collectionView != nil else { return }
        let inset = view.safeAreaInsets.bottom
        collectionView.contentInset.bottom = inset
        collectionView.verticalScrollIndicatorInsets.bottom = inset
    }

    private func setupCellRegistration() {
        cellRegistration = UICollectionView.CellRegistration<ChatListCell, Dialog> {
            [weak self] cell, indexPath, dialog in
            guard let self else { return }
            cell.configure(with: dialog, isSyncing: self.isSyncing)
            cell.setSeparatorHidden(false)
        }
    }

    private func setupDataSource() {
        dataSource = UICollectionViewDiffableDataSource<Int, String>(
            collectionView: collectionView
        ) { [weak self] collectionView, indexPath, itemId in
            guard let self, let dialog = self.dialogMap[itemId] else {
                return UICollectionViewCell()
            }
            return collectionView.dequeueConfiguredReusableCell(
                using: self.cellRegistration,
                for: indexPath,
                item: dialog
            )
        }
    }

    // MARK: - Update Data

    func updateDialogs(_ newDialogs: [Dialog], isSyncing: Bool) {
        self.isSyncing = isSyncing

        let oldIds = dialogs.map(\.id)
        let newIds = newDialogs.map(\.id)
        let structureChanged = oldIds != newIds

        self.dialogs = newDialogs
        dialogMap.removeAll(keepingCapacity: true)
        for d in newDialogs { dialogMap[d.id] = d }

        guard dataSource != nil else { return }

        if structureChanged {
            var snapshot = NSDiffableDataSourceSnapshot<Int, String>()
            snapshot.appendSections([0])
            snapshot.appendItems(newIds, toSection: 0)
            dataSource.apply(snapshot, animatingDifferences: true)
        }

        // Reconfigure visible cells
        for cell in collectionView.visibleCells {
            guard let indexPath = collectionView.indexPath(for: cell),
                  let itemId = dataSource.itemIdentifier(for: indexPath),
                  let chatCell = cell as? ChatListCell,
                  let dialog = dialogMap[itemId] else { continue }
            chatCell.configure(with: dialog, isSyncing: isSyncing)
        }
    }

    // MARK: - Swipe Actions

    private func trailingSwipeActions(for indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        guard let itemId = dataSource.itemIdentifier(for: indexPath),
              let dialog = dialogMap[itemId] else { return nil }

        let delete = UIContextualAction(style: .destructive, title: nil) { [weak self] _, _, completion in
            DispatchQueue.main.async { self?.onDeleteDialog?(dialog) }
            completion(true)
        }
        delete.image = UIImage(systemName: "trash.fill")
        delete.backgroundColor = UIColor(red: 1, green: 0.23, blue: 0.19, alpha: 1)

        return UISwipeActionsConfiguration(actions: [delete])
    }
}

// MARK: - UICollectionViewDelegate

extension RequestChatsController: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        collectionView.deselectItem(at: indexPath, animated: true)
        guard let itemId = dataSource.itemIdentifier(for: indexPath),
              let dialog = dialogMap[itemId] else { return }
        DispatchQueue.main.async { [weak self] in
            self?.onSelectDialog?(dialog)
        }
    }
}
