//
//  CozyMessageBubble.swift
//  lichunWebsocket
//
//  Cozy styled message bubble with sentiment indicators
//

import SwiftUI

struct CozyMessageBubble: View {
    @EnvironmentObject var webSocketService: WebSocketService
    let message: ConversationMessage
    let character: Person
    let isFromPlayer: Bool
    var onRetry: ((ConversationMessage) -> Void)?
    var onDelete: ((ConversationMessage) -> Void)?

    @State private var showFailedActionSheet = false

    // MARK: - Computed Properties

    private var bubbleBackground: Color {
        if isFromPlayer {
            // Softer, more visible player bubble with gradient feel
            return AppColors.playerBubble.opacity(0.85)
        } else {
            // Warm, cozy NPC bubble
            return AppColors.npcBubble
        }
    }

    private var bubbleForeground: Color {
        if isFromPlayer {
            return AppColors.playerBubbleText
        } else {
            return AppColors.npcBubbleText
        }
    }

    private var bubbleBorder: Color {
        if isFromPlayer {
            // Subtle, warm border for player messages
            return AppColors.primary.opacity(0.15)
        } else {
            // Very gentle border for NPC messages
            return AppColors.secondaryText.opacity(0.08)
        }
    }

    private var bubbleShadow: Color {
        if isFromPlayer {
            // Soft pink shadow for player bubbles
            return AppColors.primary.opacity(0.12)
        } else {
            // Warm brown shadow for NPC bubbles
            return Color.black.opacity(0.04)
        }
    }

    private var hasSentiment: Bool {
        message.sentiment == "positive" || message.sentiment == "negative"
    }

    // MARK: - Body

    @ViewBuilder
    var body: some View {
        if message.isSystemMessage {
            HStack {
                Spacer(minLength: AppSpacing.messageSpacerMinLength)

                Text(message.message)
                    .font(.appSmall)
                    .foregroundColor(AppColors.secondaryText)
                    .multilineTextAlignment(.center)
                    .padding(.horizontal, AppSpacing.md)
                    .padding(.vertical, AppSpacing.xs)
                    .background(AppColors.surfaceSubtle)
                    .cornerRadius(AppSpacing.messageBubbleCornerRadius)

                Spacer(minLength: AppSpacing.messageSpacerMinLength)
            }
        } else {
            HStack(alignment: .bottom, spacing: AppSpacing.xs) {
                if isFromPlayer {
                    Spacer(minLength: AppSpacing.messageSpacerMinLength)
                }

                VStack(alignment: isFromPlayer ? .trailing : .leading, spacing: AppSpacing.xxs) {
                    // Message bubble with cozy styling
                    Text(message.message)
                        .font(.appBody)
                        .foregroundColor(bubbleForeground)
                        .padding(.horizontal, AppSpacing.md)
                        .padding(.vertical, AppSpacing.sm)
                        .background(bubbleBackground)
                        .cornerRadius(AppSpacing.messageBubbleCornerRadius)
                        .overlay(
                            RoundedRectangle(cornerRadius: AppSpacing.messageBubbleCornerRadius)
                                .strokeBorder(bubbleBorder, lineWidth: 1.5)
                        )
                        .shadow(
                            color: bubbleShadow,
                            radius: 8,
                            x: 0,
                            y: 2
                        )
                        .overlay(
                            sentimentIndicator,
                            alignment: .bottomTrailing
                        )

                    // Status indicator and timestamp row
                    HStack(spacing: AppSpacing.xxs) {
                        // Timestamp (optional)
                        if let time = extractTime() {
                            Text(time)
                                .font(.appSmall)
                                .foregroundColor(AppColors.disabledText)
                        }

                        // Status indicator (only for player messages)
                        if isFromPlayer {
                            messageStatusIndicator
                        }
                    }
                    .padding(.horizontal, 4)
                }

                if !isFromPlayer {
                    Spacer(minLength: AppSpacing.messageSpacerMinLength)
                }
            }
        }
    }

    // MARK: - Message Status Indicator

    @ViewBuilder
    private var messageStatusIndicator: some View {
        switch message.status {
        case .pending:
            // Spinning indicator for pending messages
            ProgressView()
                .scaleEffect(0.6)
                .frame(width: 14, height: 14)

        case .sent:
            // Checkmark for sent messages
            Image(systemName: "checkmark")
                .font(.system(size: 10, weight: .semibold))
                .foregroundColor(AppColors.success)

        case .failed:
            // Tappable error indicator for failed messages
            Button(action: {
                showFailedActionSheet = true
            }) {
                HStack(spacing: 4) {
                    Image(systemName: "exclamationmark.circle.fill")
                        .font(.system(size: 12))
                        .foregroundColor(AppColors.error)

                    Text("Tap to retry")
                        .font(.system(size: 10, weight: .medium))
                        .foregroundColor(AppColors.error)
                }
            }
            .confirmationDialog(
                "Message failed to send",
                isPresented: $showFailedActionSheet,
                titleVisibility: .visible
            ) {
                Button("Retry") {
                    onRetry?(message)
                }
                Button("Delete", role: .destructive) {
                    onDelete?(message)
                }
                Button("Cancel", role: .cancel) {}
            } message: {
                if let reason = message.failureReason {
                    Text(reason)
                }
            }
            .accessibilityLabel("Message failed. Tap to retry or delete")
        }
    }

    // MARK: - Sentiment Indicator

    @ViewBuilder
    private var sentimentIndicator: some View {
        let delta = message.affinityDelta ?? (message.sentiment == "positive" ? 5 : message.sentiment == "negative" ? -5 : 0)

        if delta != 0 {
            let magnitude = abs(delta)
            let isPositive = delta > 0
            let color = badgeColor(delta: delta)

            HStack(spacing: AppSpacing.xxs) {
                Image(systemName: isPositive ? "heart.fill" : "heart.slash.fill")
                    .font(.system(size: magnitude > 15 ? 12 : 10))

                Text(isPositive ? "+\(delta)" : "\(delta)")
                    .font(.system(size: magnitude > 15 ? 12 : 10, weight: magnitude > 15 ? .bold : .medium))
            }
            .foregroundColor(color)
            .padding(.horizontal, AppSpacing.xs)
            .padding(.vertical, AppSpacing.xxs)
            .background(color.opacity(0.18))
            .cornerRadius(AppSpacing.smallCornerRadius)
            .overlay(
                RoundedRectangle(cornerRadius: AppSpacing.smallCornerRadius)
                    .strokeBorder(color.opacity(0.3), lineWidth: 1)
            )
            .shadow(
                color: color.opacity(isPositive ? 0.2 : 0.15),
                radius: AppSpacing.Shadow.offsetY,
                x: 0,
                y: 2
            )
            .offset(x: AppSpacing.sm, y: AppSpacing.sm)
            .transition(.scale.combined(with: .opacity))
        }
    }

    /// Returns an appropriate badge color scaled by affinity delta magnitude
    private func badgeColor(delta: Int) -> Color {
        if delta >= 16 { return AppColors.success }
        if delta >= 6 { return AppColors.friend }
        if delta >= 1 { return AppColors.loveInterest }
        if delta >= -8 { return Color.orange }
        if delta >= -20 { return AppColors.error }
        return AppColors.error.opacity(0.9)
    }

    // MARK: - Helper Methods

    private func extractTime() -> String? {
        // Could format message.time if available
        // For now, return nil to keep it simple
        return nil
    }
}

// MARK: - Preview
#Preview {
    CozyMessageBubblePreview()
}

private struct CozyMessageBubblePreview: View {
    var body: some View {
        let service = WebSocketService(urlSession: URLSession.shared, delegateQueue: OperationQueue())

        let character = Person()
        character.id = "1"
        character.firstname = "Emma"
        character.lastname = "Chen"

        let message1 = ConversationMessage(
            id: "1",
            message: "Hey! How are you doing today?",
            sentiment: "positive",
            answerOptions: nil,
            sender: "player",
            datetime: "2024-01-01 10:00:00.000000",
            date: "01-01",
            time: "10:00"
        )

        let message2 = ConversationMessage(
            id: "2",
            message: "I'm doing great! Thanks for asking. What about you?",
            sentiment: "positive",
            answerOptions: nil,
            sender: "1",
            datetime: "2024-01-01 10:01:00.000000",
            date: "01-01",
            time: "10:01"
        )

        return VStack(spacing: AppSpacing.md) {
            CozyMessageBubble(message: message1, character: character, isFromPlayer: true)
            CozyMessageBubble(message: message2, character: character, isFromPlayer: false)
        }
        .environmentObject(service)
        .padding()
        .background(AppColors.background)
    }
}
