import UIKit
import SwiftUI
import Combine

// MARK: - Delegate

protocol PeerProfileHeaderDelegate: AnyObject {
    func headerDidTapBack()
    func headerDidTapCall()
    func headerDidTapMuteToggle()
    func headerDidTapSearch()
    func headerDidTapMore()
    func headerDidTapMessage()
}

// MARK: - PeerProfileHeaderUIView

/// Telegram-parity expandable profile header (UIKit).
/// Collapsed: 100pt circular avatar, centered name, solid action buttons.
/// Expanded: full-width photo, left-aligned name + scrim gradient, glass buttons.
final class PeerProfileHeaderUIView: UIView {

    weak var delegate: PeerProfileHeaderDelegate?

    /// Called when header height changes — parent VC must relayout content below.
    var onHeightChanged: (() -> Void)?

    // MARK: - State

    private(set) var isLargeHeader = false {
        didSet { guard oldValue != isLargeHeader else { return }; setNeedsLayout() }
    }

    // MARK: - Configuration data

    private var displayName = ""
    private var subtitleText = ""
    private var effectiveVerified = 0
    private var avatarImage: UIImage?
    private var avatarInitials = ""
    private var avatarColorIndex = 0
    private var isMuted = false
    private var isSavedMessages = false
    private var showCallButton = true
    private var showMuteButton = true
    private var showMessageButton = false

    // MARK: - Subviews

    private let avatarClipView = UIView()
    private let avatarImageView = UIImageView()
    private let letterBackgroundView = UIView()
    private let letterOverlayView = UIView()
    private let letterLabel = UILabel()
    private let bookmarkIcon = UIImageView()

    private let scrimGradientLayer = CAGradientLayer()
    private let nameLabel = UILabel()
    private let subtitleLabel = UILabel()
    private var verifiedHosting: UIHostingController<VerifiedBadge>?

    private let backButton = UIControl()
    private let backGlassView = TelegramGlassUIView(frame: .zero)
    private let backSolidView = UIView()
    private let backChevronLayer = CAShapeLayer()

    private var actionButtons: [(UIControl, UIImageView, UILabel, TelegramGlassUIView, UIView)] = []

    // Layout constants
    private let collapsedAvatarSize: CGFloat = 100
    private let expandedHeight: CGFloat = 300
    private let buttonSpacing: CGFloat = 6
    private let horizontalPadding: CGFloat = 15

    // MARK: - Init

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    @available(*, unavailable) required init?(coder: NSCoder) { fatalError() }

    // MARK: - Configure

    func configure(
        displayName: String,
        subtitle: String,
        verified: Int,
        avatar: UIImage?,
        initials: String,
        colorIndex: Int,
        isMuted: Bool,
        isSavedMessages: Bool,
        showCall: Bool,
        showMute: Bool,
        showMessage: Bool
    ) {
        self.displayName = displayName
        self.subtitleText = subtitle
        self.effectiveVerified = verified
        self.avatarImage = avatar
        self.avatarInitials = initials
        self.avatarColorIndex = colorIndex
        self.isMuted = isMuted
        self.isSavedMessages = isSavedMessages
        self.showCallButton = showCall
        self.showMuteButton = showMute
        self.showMessageButton = showMessage

        updateContent()
        setNeedsLayout()
    }

    func updateMuted(_ muted: Bool) {
        isMuted = muted
        rebuildActionButtons()
        setNeedsLayout()
    }

    func updateSubtitle(_ text: String) {
        subtitleText = text
        subtitleLabel.text = text
    }

    func updateAvatar(_ image: UIImage?) {
        avatarImage = image
        updateAvatarContent()
    }

    var canExpand: Bool { avatarImage != nil && !isSavedMessages }

    func setLargeHeader(_ large: Bool, animated: Bool) {
        guard large != isLargeHeader else { return }
        if animated {
            UIView.animate(withDuration: 0.35, delay: 0, usingSpringWithDamping: 0.86, initialSpringVelocity: 0, options: []) {
                self.isLargeHeader = large
                self.layoutIfNeeded()
                self.onHeightChanged?()
            }
        } else {
            isLargeHeader = large
            onHeightChanged?()
        }
    }

    // MARK: - Setup

    private func setupViews() {
        clipsToBounds = false

        // Avatar clip
        avatarClipView.clipsToBounds = true
        addSubview(avatarClipView)

        avatarImageView.contentMode = .scaleAspectFill
        avatarImageView.clipsToBounds = true
        avatarClipView.addSubview(avatarImageView)

        // Letter avatar
        letterBackgroundView.clipsToBounds = true
        avatarClipView.addSubview(letterBackgroundView)

        letterOverlayView.clipsToBounds = true
        letterBackgroundView.addSubview(letterOverlayView)

        letterLabel.textAlignment = .center
        letterLabel.font = .systemFont(ofSize: 38, weight: .bold)
        letterBackgroundView.addSubview(letterLabel)

        // Saved Messages bookmark
        bookmarkIcon.image = UIImage(systemName: "bookmark.fill")
        bookmarkIcon.tintColor = .white
        bookmarkIcon.contentMode = .scaleAspectFit
        avatarClipView.addSubview(bookmarkIcon)

        // Scrim gradient
        scrimGradientLayer.colors = [
            UIColor.black.withAlphaComponent(1.0).cgColor,
            UIColor.black.withAlphaComponent(1.0).cgColor,
            UIColor.black.withAlphaComponent(0.9).cgColor,
            UIColor.black.withAlphaComponent(0.75).cgColor,
            UIColor.black.withAlphaComponent(0.55).cgColor,
            UIColor.black.withAlphaComponent(0.3).cgColor,
            UIColor.black.withAlphaComponent(0.1).cgColor,
            UIColor.clear.cgColor
        ]
        scrimGradientLayer.locations = [0.0, 0.45, 0.55, 0.65, 0.75, 0.85, 0.93, 1.0]
        scrimGradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
        scrimGradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
        avatarClipView.layer.addSublayer(scrimGradientLayer)

        // Name + subtitle
        nameLabel.font = .systemFont(ofSize: 17, weight: .semibold)
        nameLabel.textColor = .white
        addSubview(nameLabel)

        subtitleLabel.font = .systemFont(ofSize: 16)
        subtitleLabel.textColor = .secondaryLabel
        addSubview(subtitleLabel)

        // Back button
        backButton.addTarget(self, action: #selector(backTapped), for: .touchUpInside)
        addSubview(backButton)

        backGlassView.isUserInteractionEnabled = false
        backButton.addSubview(backGlassView)

        backSolidView.isUserInteractionEnabled = false
        backButton.addSubview(backSolidView)

        backChevronLayer.fillColor = UIColor.white.cgColor
        backButton.layer.addSublayer(backChevronLayer)

        rebuildActionButtons()
    }

    // MARK: - Content Updates

    private func updateContent() {
        nameLabel.text = displayName
        subtitleLabel.text = subtitleText
        updateAvatarContent()
        updateVerifiedBadge()
        rebuildActionButtons()
    }

    private func updateAvatarContent() {
        if let image = avatarImage {
            avatarImageView.image = image
            avatarImageView.isHidden = false
            letterBackgroundView.isHidden = true
            bookmarkIcon.isHidden = true
        } else if isSavedMessages {
            avatarImageView.isHidden = true
            letterBackgroundView.isHidden = true
            bookmarkIcon.isHidden = false
            avatarClipView.backgroundColor = UIColor(red: 0x24/255, green: 0x8A/255, blue: 0xE6/255, alpha: 1)
        } else {
            avatarImageView.isHidden = true
            letterBackgroundView.isHidden = false
            bookmarkIcon.isHidden = true
            avatarClipView.backgroundColor = .clear

            let colors = RosettaColors.avatarColors
            let pair = colors[avatarColorIndex % colors.count]
            let isDark = traitCollection.userInterfaceStyle == .dark
            let bgColor = isDark ? UIColor(red: 0x1A/255, green: 0x1B/255, blue: 0x1E/255, alpha: 1) : .white
            let overlayColor = UIColor(pair.tint).withAlphaComponent(isDark ? 0.15 : 0.10)
            let textColor = isDark ? UIColor(pair.text) : UIColor(pair.tint)

            letterBackgroundView.backgroundColor = bgColor
            letterOverlayView.backgroundColor = overlayColor
            letterLabel.text = avatarInitials
            letterLabel.textColor = textColor
        }
    }

    private func updateVerifiedBadge() {
        verifiedHosting?.view.removeFromSuperview()
        verifiedHosting?.removeFromParent()
        verifiedHosting = nil

        guard effectiveVerified > 0 else { return }
        let badge = VerifiedBadge(verified: effectiveVerified, size: 15, badgeTint: isLargeHeader ? .white : nil)
        let hosting = UIHostingController(rootView: badge)
        hosting.view.backgroundColor = .clear
        hosting.view.translatesAutoresizingMaskIntoConstraints = true
        addSubview(hosting.view)
        verifiedHosting = hosting
    }

    // MARK: - Action Buttons

    private func rebuildActionButtons() {
        for (control, _, _, _, _) in actionButtons {
            control.removeFromSuperview()
        }
        actionButtons.removeAll()

        var buttons: [(String, String, Selector)] = []

        if showMessageButton {
            buttons.append(("bubble.left.fill", "Message", #selector(messageTapped)))
        }
        if showCallButton {
            buttons.append(("phone.fill", "Call", #selector(callTapped)))
        }
        if showMuteButton {
            let icon = isMuted ? "bell.slash.fill" : "bell.fill"
            let title = isMuted ? "Unmute" : "Mute"
            buttons.append((icon, title, #selector(muteTapped)))
        }
        buttons.append(("magnifyingglass", "Search", #selector(searchTapped)))
        buttons.append(("ellipsis", "More", #selector(moreTapped)))

        for (icon, title, action) in buttons {
            let control = UIControl()
            control.addTarget(self, action: action, for: .touchUpInside)

            let imageView = UIImageView(image: UIImage(systemName: icon))
            imageView.contentMode = .scaleAspectFit
            imageView.tintColor = .white
            imageView.isUserInteractionEnabled = false
            control.addSubview(imageView)

            let label = UILabel()
            label.text = title
            label.font = .systemFont(ofSize: 11)
            label.textAlignment = .center
            label.textColor = .white
            label.isUserInteractionEnabled = false
            control.addSubview(label)

            let glassView = TelegramGlassUIView(frame: .zero)
            glassView.isUserInteractionEnabled = false
            control.insertSubview(glassView, at: 0)

            let solidView = UIView()
            solidView.isUserInteractionEnabled = false
            solidView.layer.cornerRadius = 15
            solidView.layer.cornerCurve = .continuous
            control.insertSubview(solidView, at: 0)

            addSubview(control)
            actionButtons.append((control, imageView, label, glassView, solidView))
        }
    }

    // MARK: - Layout

    override func layoutSubviews() {
        super.layoutSubviews()

        let w = bounds.width
        let isDark = traitCollection.userInterfaceStyle == .dark

        // --- Avatar ---
        let avatarH = isLargeHeader ? expandedHeight : collapsedAvatarSize
        let avatarW = isLargeHeader ? w : collapsedAvatarSize
        let avatarX = isLargeHeader ? 0 : (w - collapsedAvatarSize) / 2
        let avatarY: CGFloat = isLargeHeader ? 0 : 48 // expanded: fill from top; collapsed: below back button

        avatarClipView.frame = CGRect(x: avatarX, y: avatarY, width: avatarW, height: avatarH)
        avatarClipView.layer.cornerRadius = isLargeHeader ? 0 : collapsedAvatarSize / 2

        avatarImageView.frame = avatarClipView.bounds
        letterBackgroundView.frame = avatarClipView.bounds
        letterOverlayView.frame = letterBackgroundView.bounds
        bookmarkIcon.frame = CGRect(
            x: (avatarW - (isLargeHeader ? 80 : 38)) / 2,
            y: (avatarH - (isLargeHeader ? 80 : 38)) / 2,
            width: isLargeHeader ? 80 : 38,
            height: isLargeHeader ? 80 : 38
        )

        let letterSize: CGFloat = isLargeHeader ? 120 : 38
        letterLabel.font = .systemFont(ofSize: letterSize, weight: .bold)
        letterLabel.frame = letterBackgroundView.bounds

        // Scrim
        CATransaction.begin()
        CATransaction.setDisableActions(true)
        scrimGradientLayer.frame = CGRect(x: 0, y: 0, width: avatarW, height: avatarH + 40)
        scrimGradientLayer.isHidden = !isLargeHeader || avatarImage == nil
        CATransaction.commit()

        // --- Name + Subtitle ---
        let textColor: UIColor = isLargeHeader ? .white : (isDark ? .white : .black)
        nameLabel.textColor = textColor
        nameLabel.font = isLargeHeader
            ? .systemFont(ofSize: 22, weight: .semibold)
            : .systemFont(ofSize: 17, weight: .semibold)
        nameLabel.textAlignment = isLargeHeader ? .left : .center
        nameLabel.numberOfLines = isLargeHeader ? 2 : 1

        subtitleLabel.textColor = isLargeHeader
            ? UIColor.white.withAlphaComponent(0.7)
            : .secondaryLabel
        subtitleLabel.font = isLargeHeader ? .systemFont(ofSize: 16) : .systemFont(ofSize: 16)
        subtitleLabel.textAlignment = isLargeHeader ? .left : .center

        let nameY = avatarClipView.frame.maxY + 12
        let nameX = horizontalPadding
        let nameW = w - horizontalPadding * 2

        // Measure name
        let nameSize = nameLabel.sizeThatFits(CGSize(width: nameW - 24, height: 60))
        nameLabel.frame = CGRect(x: nameX, y: nameY, width: nameW, height: nameSize.height)

        // Verified badge next to name
        if let badgeView = verifiedHosting?.view {
            let badgeSize: CGFloat = isLargeHeader ? 18 : 15
            let badgeX: CGFloat
            if isLargeHeader {
                badgeX = nameX + nameSize.width + 5
            } else {
                badgeX = (w + nameSize.width) / 2 + 3
            }
            badgeView.frame = CGRect(x: badgeX, y: nameY + (nameSize.height - badgeSize) / 2, width: badgeSize, height: badgeSize)
        }

        let subtitleY = nameLabel.frame.maxY + (isLargeHeader ? 4 : 1)
        let subtitleSize = subtitleLabel.sizeThatFits(CGSize(width: nameW, height: 30))
        subtitleLabel.frame = CGRect(x: nameX, y: subtitleY, width: nameW, height: subtitleSize.height)

        // --- Action Buttons ---
        let buttonsY = subtitleLabel.frame.maxY + 20
        let btnCount = CGFloat(actionButtons.count)
        let totalSpacing = buttonSpacing * (btnCount - 1)
        let buttonW = (w - horizontalPadding * 2 - totalSpacing) / btnCount
        let buttonH: CGFloat = 58

        let btnTextColor: UIColor = isLargeHeader ? .white : UIColor(red: 0x24/255, green: 0x8A/255, blue: 0xE6/255, alpha: 1)
        let solidFill = isDark
            ? UIColor(red: 28/255, green: 28/255, blue: 29/255, alpha: 1)
            : UIColor(red: 242/255, green: 242/255, blue: 247/255, alpha: 1)

        for (i, (control, imageView, label, glassView, solidView)) in actionButtons.enumerated() {
            let x = horizontalPadding + CGFloat(i) * (buttonW + buttonSpacing)
            control.frame = CGRect(x: x, y: buttonsY, width: buttonW, height: buttonH)

            glassView.frame = control.bounds
            glassView.fixedCornerRadius = 15
            glassView.updateGlass()
            glassView.alpha = isLargeHeader ? 0.8 : 0

            solidView.frame = control.bounds
            solidView.backgroundColor = solidFill
            solidView.alpha = isLargeHeader ? 0 : 1

            imageView.tintColor = btnTextColor
            imageView.frame = CGRect(x: (buttonW - 24) / 2, y: 5, width: 24, height: 30)

            label.textColor = btnTextColor
            label.frame = CGRect(x: 0, y: 37, width: buttonW, height: 16)
        }

        // --- Back Button (positioned at top, above avatar) ---
        let backSize: CGFloat = 44
        backButton.frame = CGRect(x: horizontalPadding - 4, y: 0, width: backSize, height: backSize)

        backGlassView.frame = backButton.bounds
        backGlassView.fixedCornerRadius = backSize / 2
        backGlassView.updateGlass()
        backGlassView.alpha = isLargeHeader ? 1 : 0

        let backSolidFill = isDark
            ? UIColor.white.withAlphaComponent(0.12)
            : UIColor.black.withAlphaComponent(0.06)
        backSolidView.frame = backButton.bounds
        backSolidView.layer.cornerRadius = backSize / 2
        backSolidView.backgroundColor = backSolidFill
        backSolidView.alpha = isLargeHeader ? 0 : 1

        let chevronColor: UIColor = isLargeHeader ? .white : (isDark ? .white : .black)
        backChevronLayer.fillColor = chevronColor.cgColor
        updateBackChevronPath()

        // Total height
        let totalH = buttonsY + buttonH + horizontalPadding
        if abs(bounds.height - totalH) > 1 {
            frame.size.height = totalH
        }
    }

    func preferredHeight() -> CGFloat {
        let avatarH = isLargeHeader ? expandedHeight : collapsedAvatarSize
        // backButton(44) + spacing(4) + avatar + spacing(12) + name(~22) + spacing(4) + subtitle(~20) + spacing(20) + buttons(58) + bottomPad(15)
        return 44 + 4 + avatarH + 12 + 22 + 4 + 20 + 20 + 58 + horizontalPadding
    }

    private func updateBackChevronPath() {
        let iconSize = CGSize(width: 11, height: 20)
        let origin = CGPoint(
            x: (backButton.bounds.width - iconSize.width) / 2,
            y: (backButton.bounds.height - iconSize.height) / 2
        )
        let vb = CGSize(width: 10.7, height: 19.63)
        var parser = SVGPathParser(pathData: TelegramIconPath.backChevron)
        let rawPath = parser.parse()
        var transform = CGAffineTransform(translationX: origin.x, y: origin.y)
            .scaledBy(x: iconSize.width / vb.width, y: iconSize.height / vb.height)
        let scaledPath = rawPath.copy(using: &transform)
        backChevronLayer.path = scaledPath
        backChevronLayer.frame = backButton.bounds
    }

    // MARK: - Trait Changes

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        if traitCollection.userInterfaceStyle != previousTraitCollection?.userInterfaceStyle {
            updateAvatarContent()
            updateVerifiedBadge()
            setNeedsLayout()
        }
    }

    // MARK: - Actions

    @objc private func backTapped() { delegate?.headerDidTapBack() }
    @objc private func callTapped() { delegate?.headerDidTapCall() }
    @objc private func muteTapped() { delegate?.headerDidTapMuteToggle() }
    @objc private func searchTapped() { delegate?.headerDidTapSearch() }
    @objc private func moreTapped() { delegate?.headerDidTapMore() }
    @objc private func messageTapped() { delegate?.headerDidTapMessage() }
}
