import UIKit
import SwiftUI

/// Screen 1: "New Message" compose screen — Telegram parity.
/// Custom glass header: X close button + "New Message" title.
/// Glass search bar capsule, "New Group" / "Join Group" options, contact list.
final class ComposeViewController: UIViewController {

    // MARK: - Callbacks

    var onOpenChat: ((ChatRoute) -> Void)?

    // MARK: - Data

    private var allContacts: [Dialog] = []
    private var filteredContacts: [Dialog] = []
    private var searchQuery = ""

    // MARK: - Sections

    private enum Section: Int, CaseIterable {
        case options
        case contacts
    }

    private enum OptionRow: Int, CaseIterable {
        case newGroup
        case joinGroup
    }

    // MARK: - Header Views

    private let headerBarHeight: CGFloat = 44
    private let closeButton = ComposeGlassCloseButton()
    private let titleLabel = UILabel()
    private let glassSearchBar = ComposeGlassSearchBar()

    // MARK: - Content Views

    private var collectionView: UICollectionView!
    private var observationTask: Task<Void, Never>?

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor { $0.userInterfaceStyle == .dark ? .black : .white }
        hidesBottomBarWhenPushed = true

        setupCustomHeader()
        setupGlassSearchBar()
        setupCollectionView()
        loadContacts()
        startObservationLoop()
    }

    deinit {
        observationTask?.cancel()
    }

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

    // MARK: - Custom Glass Header

    private func setupCustomHeader() {
        closeButton.addTarget(self, action: #selector(closeTapped), for: .touchUpInside)
        closeButton.layer.zPosition = 55
        view.addSubview(closeButton)

        titleLabel.text = "New Message"
        titleLabel.font = .systemFont(ofSize: 17, weight: .semibold)
        titleLabel.textColor = UIColor(RosettaColors.Adaptive.text)
        titleLabel.textAlignment = .center
        titleLabel.layer.zPosition = 55
        view.addSubview(titleLabel)
    }

    private func setupGlassSearchBar() {
        glassSearchBar.placeholder = "Search"
        glassSearchBar.onTextChanged = { [weak self] text in
            self?.searchQuery = text
            self?.applySearch()
        }
        glassSearchBar.layer.zPosition = 55
        view.addSubview(glassSearchBar)
    }

    private func layoutCustomHeader() {
        let safeTop = view.safeAreaInsets.top
        let centerY = safeTop + headerBarHeight * 0.5

        // Close button (left)
        let closeSize = closeButton.intrinsicContentSize
        closeButton.frame = CGRect(
            x: 8,
            y: centerY - closeSize.height * 0.5,
            width: closeSize.width,
            height: closeSize.height
        )

        // Title (center)
        let titleWidth: CGFloat = 200
        titleLabel.frame = CGRect(
            x: (view.bounds.width - titleWidth) / 2,
            y: centerY - 11,
            width: titleWidth,
            height: 22
        )

        // Search bar (below header) — 44pt height matching chat list
        let searchY = safeTop + headerBarHeight + 8
        glassSearchBar.frame = CGRect(
            x: 16,
            y: searchY,
            width: view.bounds.width - 32,
            height: 44
        )
    }

    // MARK: - Collection View

    private func setupCollectionView() {
        let layout = createLayout()
        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.backgroundColor = .clear
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.keyboardDismissMode = .onDrag
        collectionView.register(ComposeOptionCell.self, forCellWithReuseIdentifier: ComposeOptionCell.reuseID)
        collectionView.register(ComposeContactCell.self, forCellWithReuseIdentifier: ComposeContactCell.reuseID)
        collectionView.register(
            ComposeSectionHeaderView.self,
            forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
            withReuseIdentifier: "SectionHeader"
        )

        view.addSubview(collectionView)

        // Collection starts below header + search bar
        let topOffset = headerBarHeight + 8 + 44 + 8 // header + spacing + search(44pt) + spacing
        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: topOffset),
            collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        ])

        // Bring header views above collection
        view.bringSubviewToFront(closeButton)
        view.bringSubviewToFront(titleLabel)
        view.bringSubviewToFront(glassSearchBar)
    }

    private func createLayout() -> UICollectionViewCompositionalLayout {
        UICollectionViewCompositionalLayout { [weak self] sectionIndex, _ in
            guard let section = Section(rawValue: sectionIndex) else { return nil }
            switch section {
            case .options:
                return self?.optionsSectionLayout()
            case .contacts:
                return self?.contactsSectionLayout()
            }
        }
    }

    private func optionsSectionLayout() -> NSCollectionLayoutSection {
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(48))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(48))
        let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
        return NSCollectionLayoutSection(group: group)
    }

    private func contactsSectionLayout() -> NSCollectionLayoutSection {
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(56))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(56))
        let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
        let section = NSCollectionLayoutSection(group: group)

        let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(36))
        let header = NSCollectionLayoutBoundarySupplementaryItem(
            layoutSize: headerSize,
            elementKind: UICollectionView.elementKindSectionHeader,
            alignment: .top
        )
        section.boundarySupplementaryItems = [header]

        return section
    }

    // MARK: - Data Loading

    private func loadContacts() {
        let dialogs = DialogRepository.shared.dialogs
        allContacts = dialogs.values
            .filter { !$0.isGroup && !$0.isSavedMessages && !SystemAccounts.isSystemAccount($0.opponentKey) }
            .sorted { $0.opponentTitle.localizedCaseInsensitiveCompare($1.opponentTitle) == .orderedAscending }
        applySearch()
    }

    private func applySearch() {
        if searchQuery.isEmpty {
            filteredContacts = allContacts
        } else {
            let query = searchQuery.lowercased()
            filteredContacts = allContacts.filter {
                $0.opponentTitle.lowercased().contains(query) ||
                $0.opponentUsername.lowercased().contains(query)
            }
        }
        collectionView?.reloadData()
    }

    private func startObservationLoop() {
        // dialogsVersion is @ObservationIgnored — track dialogs directly
        observationTask = Task { @MainActor [weak self] in
            while !Task.isCancelled {
                guard let self else { return }
                withObservationTracking {
                    _ = DialogRepository.shared.dialogs
                } onChange: { }
                try? await Task.sleep(for: .milliseconds(500))
                guard !Task.isCancelled else { return }
                self.loadContacts()
            }
        }
    }

    // MARK: - Actions

    @objc private func closeTapped() {
        navigationController?.popViewController(animated: true)
    }

    private func openNewGroup() {
        let picker = GroupContactPickerViewController()
        picker.onOpenChat = onOpenChat
        navigationController?.pushViewController(picker, animated: true)
    }

    private func openJoinGroup() {
        let root = NavigationStack {
            GroupJoinView { [weak self] route in
                guard let self else { return }
                self.dismiss(animated: true) {
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                        self.onOpenChat?(route)
                    }
                }
            }
        }
        let host = UIHostingController(rootView: root)
        host.modalPresentationStyle = .pageSheet
        if let sheet = host.sheetPresentationController {
            sheet.detents = [.large()]
        }
        present(host, animated: true)
    }
}

// MARK: - UICollectionViewDataSource

extension ComposeViewController: UICollectionViewDataSource {

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        Section.allCases.count
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        switch Section(rawValue: section) {
        case .options: return OptionRow.allCases.count
        case .contacts: return filteredContacts.count
        case .none: return 0
        }
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        switch Section(rawValue: indexPath.section) {
        case .options:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ComposeOptionCell.reuseID, for: indexPath) as! ComposeOptionCell
            let option = OptionRow(rawValue: indexPath.item)!
            switch option {
            case .newGroup:
                cell.configure(icon: UIImage(systemName: "person.2.fill"), title: "New Group", showSeparator: true)
            case .joinGroup:
                cell.configure(icon: UIImage(systemName: "link.badge.plus"), title: "Join Group", showSeparator: false)
            }
            return cell
        case .contacts:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ComposeContactCell.reuseID, for: indexPath) as! ComposeContactCell
            cell.configure(with: filteredContacts[indexPath.item], isSelected: false, showCheckmark: false)
            return cell
        case .none:
            return UICollectionViewCell()
        }
    }

    func collectionView(
        _ collectionView: UICollectionView,
        viewForSupplementaryElementOfKind kind: String,
        at indexPath: IndexPath
    ) -> UICollectionReusableView {
        switch Section(rawValue: indexPath.section) {
        case .contacts:
            let header = collectionView.dequeueReusableSupplementaryView(
                ofKind: kind,
                withReuseIdentifier: "SectionHeader",
                for: indexPath
            ) as! ComposeSectionHeaderView
            header.configure(title: filteredContacts.isEmpty ? "" : "CHATS")
            return header
        default:
            collectionView.register(UICollectionReusableView.self, forSupplementaryViewOfKind: kind, withReuseIdentifier: "Empty")
            return collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Empty", for: indexPath)
        }
    }
}

// MARK: - UICollectionViewDelegate

extension ComposeViewController: UICollectionViewDelegate {

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        collectionView.deselectItem(at: indexPath, animated: true)

        switch Section(rawValue: indexPath.section) {
        case .options:
            switch OptionRow(rawValue: indexPath.item)! {
            case .newGroup: openNewGroup()
            case .joinGroup: openJoinGroup()
            }
        case .contacts:
            let route = ChatRoute(dialog: filteredContacts[indexPath.item])
            if let navController = navigationController {
                navController.popToRootViewController(animated: false)
                DispatchQueue.main.async { self.onOpenChat?(route) }
            }
        case .none:
            break
        }
    }
}

// MARK: - Section Header View

final class ComposeSectionHeaderView: UICollectionReusableView {

    private let label = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        label.font = .systemFont(ofSize: 13, weight: .regular)
        label.textColor = UIColor(RosettaColors.Adaptive.textSecondary)
        label.translatesAutoresizingMaskIntoConstraints = false
        addSubview(label)
        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4),
        ])
    }

    required init?(coder: NSCoder) { fatalError() }

    func configure(title: String) {
        label.text = title
    }
}
