import SwiftUI

// MARK: - In-App Notification Banner (Telegram parity)

/// Telegram-style in-app notification banner shown when a message arrives
/// while the app is in foreground and the user is NOT in that chat.
///
/// Specs (from Telegram iOS `ChatMessageNotificationItem.swift` + `NotificationItemContainerNode.swift`):
/// - Panel: 74pt min height, 24pt corner radius, 8pt horizontal margin
/// - Avatar: 54pt circle, 12pt left inset, 23pt avatar-to-text spacing
/// - Title: semibold 16pt, white, 1 line
/// - Message: regular 16pt, white (full), max 2 lines
/// - Background: TelegramGlass (CABackdropLayer / UIGlassEffect)
/// - Slide from top: 0.4s, auto-dismiss: 5s, swipe dismiss with 0.55 damping
struct InAppBannerView: View {
    let senderName: String
    let messagePreview: String
    let senderKey: String
    let isGroup: Bool
    let onTap: () -> Void
    let onDismiss: () -> Void

    @State private var dragOffset: CGFloat = 0

    private let panelHeight: CGFloat = 74
    private let cornerRadius: CGFloat = 24
    private let avatarSize: CGFloat = 54
    private let horizontalMargin: CGFloat = 8

    var body: some View {
        HStack(spacing: 23) {
            avatarView
            VStack(alignment: .leading, spacing: 1) {
                Text(senderName)
                    .font(.system(size: 16, weight: .semibold))
                    .foregroundStyle(.white)
                    .lineLimit(1)
                Text(messagePreview)
                    .font(.system(size: 16))
                    .foregroundStyle(.white)
                    .lineLimit(2)
            }
            Spacer(minLength: 0)
        }
        .padding(.leading, 12)
        .padding(.trailing, 10)
        .frame(minHeight: panelHeight)
        .frame(maxWidth: .infinity)
        .glass(cornerRadius: cornerRadius)
        .padding(.horizontal, horizontalMargin)
        .offset(y: dragOffset)
        .gesture(
            DragGesture(minimumDistance: 5)
                .onChanged { value in
                    let translation = value.translation.height
                    if translation < 0 {
                        // Dragging up — full 1:1 tracking.
                        dragOffset = translation
                    } else {
                        // Dragging down — logarithmic rubber-band (Telegram: 0.55/50 cap).
                        // Formula: -((1 - 1/((delta*0.55/50)+1)) * 50)
                        let delta = translation
                        dragOffset = (1.0 - (1.0 / ((delta * 0.55 / 50.0) + 1.0))) * 50.0
                    }
                }
                .onEnded { value in
                    let velocity = value.predictedEndTranslation.height - value.translation.height
                    // Dismiss: swiped up > 20pt or fast upward velocity (Telegram: -20pt / 300pt/s).
                    if value.translation.height < -20 || velocity < -300 {
                        withAnimation(.easeOut(duration: 0.4)) {
                            dragOffset = -200
                        }
                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
                            onDismiss()
                        }
                    } else {
                        // Spring back (Telegram: 0.3s easeInOut).
                        withAnimation(.easeInOut(duration: 0.3)) {
                            dragOffset = 0
                        }
                    }
                }
        )
        .onTapGesture {
            onTap()
        }
        .contentShape(Rectangle())
    }

    @ViewBuilder
    private var avatarView: some View {
        let colorIndex = Self.avatarColorIndex(for: senderName, publicKey: senderKey)
        let pair = Self.avatarColors[colorIndex % Self.avatarColors.count]

        if isGroup {
            // Group: solid tint circle + person.2.fill (ChatRowView parity).
            ZStack {
                Circle().fill(Color(hex: UInt(pair.tint)))
                Image(systemName: "person.2.fill")
                    .font(.system(size: 20, weight: .medium))
                    .foregroundStyle(.white.opacity(0.9))
            }
            .frame(width: avatarSize, height: avatarSize)
        } else {
            // Personal: Mantine "light" variant (AvatarView parity).
            let avatarImage = AvatarRepository.shared.loadAvatar(publicKey: senderKey)
            if let image = avatarImage {
                Image(uiImage: image)
                    .resizable()
                    .scaledToFill()
                    .frame(width: avatarSize, height: avatarSize)
                    .clipShape(Circle())
            } else {
                ZStack {
                    Circle().fill(Color(hex: 0x1A1B1E))
                    Circle().fill(Color(hex: UInt(pair.tint)).opacity(0.15))
                    Text(Self.initials(name: senderName, publicKey: senderKey))
                        .font(.system(size: avatarSize * 0.38, weight: .bold, design: .rounded))
                        .foregroundStyle(Color(hex: UInt(pair.text)))
                }
                .frame(width: avatarSize, height: avatarSize)
            }
        }
    }

    // MARK: - Color helpers (duplicated from Colors.swift — NSE can't import main target)

    private static let avatarColors: [(tint: UInt32, text: UInt32)] = [
        (0x228be6, 0x74c0fc), (0x15aabf, 0x66d9e8), (0xbe4bdb, 0xe599f7),
        (0x40c057, 0x8ce99a), (0x4c6ef5, 0x91a7ff), (0x82c91e, 0xc0eb75),
        (0xfd7e14, 0xffc078), (0xe64980, 0xfaa2c1), (0xfa5252, 0xffa8a8),
        (0x12b886, 0x63e6be), (0x7950f2, 0xb197fc),
    ]

    private static func avatarColorIndex(for name: String, publicKey: String) -> Int {
        let trimmed = name.trimmingCharacters(in: .whitespaces)
        let input = trimmed.isEmpty ? String(publicKey.prefix(7)) : trimmed
        var hash: Int32 = 0
        for char in input.unicodeScalars {
            hash = (hash &<< 5) &- hash &+ Int32(truncatingIfNeeded: char.value)
        }
        let count = Int32(avatarColors.count)
        var index = abs(hash) % count
        if index < 0 { index += count }
        return Int(index)
    }

    private static func initials(name: String, publicKey: String) -> String {
        let words = name.trimmingCharacters(in: .whitespaces)
            .split(whereSeparator: { $0.isWhitespace })
            .filter { !$0.isEmpty }
        switch words.count {
        case 0:
            return publicKey.isEmpty ? "??" : String(publicKey.prefix(2)).uppercased()
        case 1:
            return String(words[0].prefix(2)).uppercased()
        default:
            let first = words[0].first.map(String.init) ?? ""
            let second = words[1].first.map(String.init) ?? ""
            return (first + second).uppercased()
        }
    }
}
