//
//  TypingIndicatorBubble.swift
//  lichunWebsocket
//
//  Animated typing indicator that mimics a real person typing
//

import SwiftUI

struct TypingIndicatorBubble: View {
    let character: Person

    // Animation state for each dot
    @State private var dot1Active = false
    @State private var dot2Active = false
    @State private var dot3Active = false

    // Appearance animation
    @State private var isVisible = false

    // Timer reference for cleanup
    @State private var dotTimer: Timer?

    private let dotSize: CGFloat = 8
    private let bubblePadding: CGFloat = 14

    var body: some View {
        HStack(alignment: .bottom, spacing: AppSpacing.sm) {
            // Character avatar (small)
            CharacterAvatar(
                person: character,
                size: 28,
                showBorder: false,
                showGlow: false
            )

            // Typing bubble
            HStack(spacing: 6) {
                Circle()
                    .fill(AppColors.secondaryText.opacity(0.6))
                    .frame(width: dotSize, height: dotSize)
                    .offset(y: dot1Active ? -4 : 0)

                Circle()
                    .fill(AppColors.secondaryText.opacity(0.6))
                    .frame(width: dotSize, height: dotSize)
                    .offset(y: dot2Active ? -4 : 0)

                Circle()
                    .fill(AppColors.secondaryText.opacity(0.6))
                    .frame(width: dotSize, height: dotSize)
                    .offset(y: dot3Active ? -4 : 0)
            }
            .padding(.horizontal, bubblePadding + 4)
            .padding(.vertical, bubblePadding)
            .background(
                RoundedRectangle(cornerRadius: 18)
                    .fill(AppColors.npcBubble)
            )
            .overlay(
                RoundedRectangle(cornerRadius: 18)
                    .strokeBorder(AppColors.secondaryText.opacity(0.15), lineWidth: 0.5)
            )

            Spacer()
        }
        .padding(.leading, AppSpacing.sm)
        .opacity(isVisible ? 1 : 0)
        .offset(y: isVisible ? 0 : 4)
        .onAppear {
            // Clean up any stale timer from LazyVStack recycling
            dotTimer?.invalidate()
            dotTimer = nil

            // Fast fade in
            withAnimation(.easeOut(duration: 0.12)) {
                isVisible = true
            }

            // Start dot animation immediately
            startDotAnimation()
        }
        .onDisappear {
            // Invalidate timer to prevent leak
            dotTimer?.invalidate()
            dotTimer = nil
        }
    }

    private func startDotAnimation() {
        let baseAnimation = Animation.easeInOut(duration: 0.35)

        // Continuous loop with staggered timing
        dotTimer = Timer.scheduledTimer(withTimeInterval: 0.6, repeats: true) { _ in
            // Dot 1
            withAnimation(baseAnimation) {
                dot1Active = true
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                withAnimation(baseAnimation) {
                    dot1Active = false
                }
            }

            // Dot 2 (delayed)
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
                withAnimation(baseAnimation) {
                    dot2Active = true
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                    withAnimation(baseAnimation) {
                        dot2Active = false
                    }
                }
            }

            // Dot 3 (more delayed)
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                withAnimation(baseAnimation) {
                    dot3Active = true
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                    withAnimation(baseAnimation) {
                        dot3Active = false
                    }
                }
            }
        }
    }
}

// MARK: - Preview

#if DEBUG
struct TypingIndicatorBubble_Previews: PreviewProvider {
    static var previews: some View {
        let person = Person()
        person.firstname = "Emma"
        person.image = ""

        return VStack {
            Spacer()
            TypingIndicatorBubble(character: person)
                .padding()
            Spacer()
        }
        .background(AppColors.background)
    }
}
#endif
