//
//  LifeEventCard.swift
//  lichunWebsocket
//
//  Individual claimable/claimed event card
//

import SwiftUI
import UIKit
import SDWebImageSwiftUI

struct LifeEventCard: View {
    @EnvironmentObject var webSocketService: WebSocketService
    let event: MessageEvent
    let unclaimedIndex: Int? // Position among unclaimed events (0-based)

    @State private var isPulsing = false
    @State private var isClaiming = false
    @State private var showConfetti = false
    @State private var cachedPersons: [String: Person] = [:]

    var body: some View {
        Button(action: {
            if event.isClaimable && !event.claimed {
                claimEvent()
            }
        }) {
            VStack(alignment: .leading, spacing: AppSpacing.xs) {

                // NEW: Character avatars row
                if let characters = event.characters, !characters.isEmpty {
                    HStack(spacing: -AppSpacing.sm) {
                        ForEach(characters.prefix(4)) { character in
                            CharacterAvatar(
                                person: personFrom(character),
                                size: AppSpacing.iconSizeLarge,
                                showBorder: true,
                                borderGradient: [.white, .white.opacity(0.8)],
                                showGlow: false
                            )
                        }
                    }
                    .padding(.bottom, AppSpacing.xxs)
                }

                // Event content
                HStack(alignment: .top, spacing: AppSpacing.sm) {
                    // Category icon
                    Text(event.category.rawValue)
                        .font(.system(size: AppSpacing.iconSizeLarge))
                        .lineLimit(1)

                    VStack(alignment: .leading, spacing: AppSpacing.xxs) {
                        // Event message
                        Text(event.message)
                            .font(.appBody)
                            .foregroundColor(AppColors.primaryText)
                            .multilineTextAlignment(.leading)
                            .lineLimit(3)

                        if statusDisplayText != nil || categoryDisplayText != nil {
                            HStack(spacing: AppSpacing.xs) {
                                if let statusDisplayText {
                                    Text(statusDisplayText)
                                        .font(.appSmall)
                                        .foregroundColor(AppColors.primary)
                                        .padding(.horizontal, AppSpacing.xs)
                                        .padding(.vertical, 2)
                                        .background(
                                            Capsule()
                                                .fill(AppColors.primary.opacity(0.12))
                                        )
                                }

                                if let categoryDisplayText {
                                    Text(categoryDisplayText)
                                        .font(.appSmall)
                                        .foregroundColor(AppColors.secondaryText)
                                        .lineLimit(1)
                                }
                            }
                        }

                        // State-specific content
                        if event.isClaimable && !event.claimed {
                            // Unclaimed state
                            HStack(spacing: 4) {
                                Image(systemName: "hand.tap.fill")
                                    .font(.system(size: 12))
                                Text("Tap to claim:")
                                    .font(.appCaption)
                            }
                            .foregroundColor(AppColors.primary)

                            rewardDisplay
                                .foregroundColor(AppColors.secondaryText)

                        } else if event.claimed && event.isClaimable {
                            // Claimed state with rewards
                            HStack(spacing: 4) {
                                Image(systemName: "checkmark.circle.fill")
                                    .font(.system(size: 12))
                                    .foregroundColor(AppColors.success)
                                Text("Earned:")
                                    .font(.appCaption)
                            }

                            rewardDisplay
                                .foregroundColor(AppColors.primaryText)

                            if let claimedAt = event.claimedAt {
                                Text(timeAgo(from: claimedAt))
                                    .font(.appSmall)
                                    .foregroundColor(AppColors.disabledText)
                            }

                        } else if event.isNegative {
                            // Negative events
                            lossDisplay
                                .foregroundColor(AppColors.error)

                            Text(timeAgo(from: event.claimedAt ?? Date()))
                                .font(.appSmall)
                                .foregroundColor(AppColors.disabledText)

                        } else {
                            // Neutral events (no rewards, no losses)
                            if let claimedAt = event.claimedAt {
                                Text(timeAgo(from: claimedAt))
                                    .font(.appSmall)
                                    .foregroundColor(AppColors.disabledText)
                            }
                        }
                    }

                    Spacer()
                }
            }
            .padding(AppSpacing.md)
            .background(backgroundContent)
            .cornerRadius(AppSpacing.cornerRadius)
            .overlay(
                RoundedRectangle(cornerRadius: AppSpacing.cornerRadius)
                    .strokeBorder(borderGradient, lineWidth: borderWidth)
            )
            .shadow(color: shadowColor, radius: shadowRadius, x: 0, y: 2)
            .scaleEffect(isClaiming ? 0.95 : 1.0)
            .opacity(event.claimed ? 0.7 : 1.0)
            .overlay(
                // Confetti overlay
                Group {
                    if showConfetti {
                        ConfettiView()
                    }
                }
            )
        }
        .buttonStyle(PlainButtonStyle())
        .disabled(event.claimed || !event.isClaimable)
        .onAppear {
            // Only pulse first 5 unclaimed events for performance
            if event.isClaimable && !event.claimed,
               let index = unclaimedIndex,
               index < 5 {
                startPulseAnimation()
            }
        }
    }

    // MARK: - Computed Properties

    var backgroundColor: Color {
        if event.isClaimable && !event.claimed {
            return AppColors.surfaceElevated
        } else if event.isNegative {
            return AppColors.error.opacity(0.08)
        } else {
            return AppColors.surfaceSubtle
        }
    }

    var borderGradient: LinearGradient {
        if event.isClaimable && !event.claimed {
            return LinearGradient(
                colors: [AppColors.primary.opacity(0.6), AppColors.accent.opacity(0.6)],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
        } else {
            return LinearGradient(
                colors: [Color.clear],
                startPoint: .top,
                endPoint: .bottom
            )
        }
    }

    var borderWidth: CGFloat {
        event.isClaimable && !event.claimed ? 2 : 0
    }

    var shadowColor: Color {
        if event.isClaimable && !event.claimed {
            return AppColors.primary.opacity(isPulsing ? 0.3 : 0.15)
        } else {
            return Color.black.opacity(0.04)
        }
    }

    var shadowRadius: CGFloat {
        event.isClaimable && !event.claimed ? 10 : 5
    }

    @ViewBuilder
    private var backgroundContent: some View {
        ZStack {
            // Base background color
            backgroundColor

            // Optional location image overlay
            if let imageURL = event.image?.trimmingCharacters(in: .whitespacesAndNewlines),
               !imageURL.isEmpty,
               let url = URL(string: imageURL) {
                WebImage(url: url)
                    .onSuccess { image, data, cacheType in
                        print("📍 EventImage: ✅ Loaded event image - size: \(image.size), cache: \(cacheType)")
                    }
                    .onFailure { error in
                        print("📍 EventImage: ❌ Failed event image - URL: \(imageURL) - Error: \(error.localizedDescription)")
                    }
                    .resizable()
                    .placeholder {
                        EmptyView()
                            .onAppear {
                                print("📍 EventImage: 🔄 Loading event image from: \(imageURL)")
                            }
                    }
                    .aspectRatio(contentMode: .fill)
                    .opacity(0.15)
                    .blur(radius: 2)
            }
        }
    }

    private var statusDisplayText: String? {
        guard let value = event.status?.trimmingCharacters(in: .whitespacesAndNewlines),
              !value.isEmpty else {
            return nil
        }

        return value
            .replacingOccurrences(of: "_", with: " ")
            .capitalized
    }

    private var categoryDisplayText: String? {
        guard let value = event.categoryKey?.trimmingCharacters(in: .whitespacesAndNewlines),
              !value.isEmpty else {
            return nil
        }

        return value
            .replacingOccurrences(of: "_", with: " ")
            .capitalized
    }

    var rewardDisplay: some View {
        HStack(spacing: AppSpacing.xs) {
            if let money = event.moneyCost, money > 0 {
                Text("+$\(money) 💰")
                    .font(.appCaption)
            }
            if let energy = event.energyCost, energy > 0 {
                Text("+\(energy) ⚡")
                    .font(.appCaption)
            }
            if let diamonds = event.diamondCost, diamonds > 0 {
                Text("+\(diamonds) 💎")
                    .font(.appCaption)
            }
            if let affinity = event.affinityChange, affinity > 0 {
                Text("+\(affinity) ❤️")
                    .font(.appCaption)
            }
        }
    }

    var lossDisplay: some View {
        HStack(spacing: AppSpacing.xs) {
            Text("Lost:")
                .font(.appCaption)
                .foregroundColor(AppColors.primaryText)

            if let money = event.moneyCost, money < 0 {
                Text("-$\(abs(money)) 💰")
                    .font(.appCaption)
                    .foregroundColor(AppColors.primaryText)
            }
            if let energy = event.energyCost, energy < 0 {
                Text("\(energy) ⚡")
                    .font(.appCaption)
                    .foregroundColor(AppColors.primaryText)
            }
        }
    }

    // MARK: - Actions

    func claimEvent() {
        // Haptic feedback
        let generator = UIImpactFeedbackGenerator(style: .medium)
        generator.impactOccurred()

        // Animation
        withAnimation(.spring(response: 0.3, dampingFraction: 0.6)) {
            isClaiming = true
        }

        // Show confetti
        showConfetti = true

        // Send claim to backend
        webSocketService.claimEvent(event)

        // Success haptic after delay
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
            let notification = UINotificationFeedbackGenerator()
            notification.notificationOccurred(.success)
        }

        // Reset animation
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
            withAnimation {
                isClaiming = false
                showConfetti = false
            }
        }
    }

    func startPulseAnimation() {
        withAnimation(.easeInOut(duration: 2.0).repeatForever(autoreverses: true)) {
            isPulsing = true
        }
    }

    func timeAgo(from date: Date) -> String {
        let interval = Date().timeIntervalSince(date)

        if interval < 60 {
            return "Just now"
        } else if interval < 3600 {
            let minutes = Int(interval / 60)
            return "\(minutes) minute\(minutes == 1 ? "" : "s") ago"
        } else if interval < 86400 {
            let hours = Int(interval / 3600)
            return "\(hours) hour\(hours == 1 ? "" : "s") ago"
        } else {
            let days = Int(interval / 86400)
            return "\(days) day\(days == 1 ? "" : "s") ago"
        }
    }

    // MARK: - Helpers

    /// Convert SimplePerson to Person for AvatarView (with caching)
    private func personFrom(_ simple: SimplePerson) -> Person {
        // Check cache first
        if let cached = cachedPersons[simple.id] {
            return cached
        }

        // Create new Person and cache it
        let person = Person()
        person.id = simple.id
        person.firstname = simple.firstname
        person.lastname = simple.lastname
        person.image = simple.image
        cachedPersons[simple.id] = person
        return person
    }
}

// MARK: - Preview
#Preview {
    let testCharacter1 = SimplePerson(
        id: "1",
        firstname: "John",
        lastname: "Doe",
        image: "https://api.dicebear.com/7.x/avataaars/svg?seed=John"
    )
    let testCharacter2 = SimplePerson(
        id: "2",
        firstname: "Jane",
        lastname: "Smith",
        image: "https://api.dicebear.com/7.x/avataaars/svg?seed=Jane"
    )

    return VStack(spacing: AppSpacing.md) {
        // Event with avatars and location
        LifeEventCard(
            event: MessageEvent(
                id: "1",
                message: "You had lunch with friends at the cafeteria",
                type: "messageEvent",
                date: nil,
                hour: nil,
                energyCost: nil,
                diamondCost: nil,
                moneyCost: nil,
                affinityChange: 5,
                title: nil,
                image: "https://cdn.discordapp.com/attachments/1106614533402931284/cafeteria.png",
                characters: [testCharacter1, testCharacter2],
                claimed: false,
                claimedAt: nil,
                category: .social
            ),
            unclaimedIndex: 0
        )

        // Unclaimed event
        LifeEventCard(
            event: MessageEvent(
                id: "2",
                message: "Promoted to Senior Manager",
                type: "messageEvent",
                date: nil,
                hour: nil,
                energyCost: nil,
                diamondCost: nil,
                moneyCost: 500,
                affinityChange: nil,
                title: nil,
                image: nil,
                claimed: false,
                claimedAt: nil,
                category: .career
            ),
            unclaimedIndex: 1
        )

        // Claimed event
        LifeEventCard(
            event: MessageEvent(
                id: "3",
                message: "Graduated from University",
                type: "messageEvent",
                date: nil,
                hour: nil,
                energyCost: nil,
                diamondCost: nil,
                moneyCost: 200,
                affinityChange: nil,
                title: nil,
                image: nil,
                claimed: true,
                claimedAt: Date().addingTimeInterval(-3600 * 6),
                category: .education
            ),
            unclaimedIndex: nil
        )

        // Negative event
        LifeEventCard(
            event: MessageEvent(
                id: "4",
                message: "Car broke down",
                type: "messageEvent",
                date: nil,
                hour: nil,
                energyCost: nil,
                diamondCost: nil,
                moneyCost: -800,
                affinityChange: nil,
                title: nil,
                image: nil,
                claimed: true,
                claimedAt: Date().addingTimeInterval(-1800),
                category: .negative
            ),
            unclaimedIndex: nil
        )
    }
    .environmentObject(WebSocketService(urlSession: URLSession.shared, delegateQueue: OperationQueue()))
    .padding()
    .background(AppColors.background)
}
