//
//  ToastManager.swift
//  lichunWebsocket
//
//  Centralized toast notification management
//

import SwiftUI
import Combine

// MARK: - Toast Manager
class ToastManager: ObservableObject {
    static let shared = ToastManager()

    @Published var currentToast: ToastItem?
    @Published private(set) var toastQueue: [ToastItem] = []

    private var timer: Timer?

    private init() {}

    // MARK: - Public API

    /// Show a toast with specific type and message
    func show(_ type: ToastType, message: String, duration: TimeInterval = 3.0) {
        let toast = ToastItem(type: type, message: message, duration: duration)

        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }

            if self.currentToast == nil {
                self.showToast(toast)
            } else {
                self.toastQueue.append(toast)
            }
        }
    }

    /// Show a success toast
    func showSuccess(_ message: String, duration: TimeInterval = 3.0) {
        show(.success, message: message, duration: duration)
    }

    /// Show an error toast
    func showError(_ message: String, duration: TimeInterval = 3.0) {
        show(.error, message: message, duration: duration)
        hapticNotification(type: .error)
    }

    /// Show an info toast
    func showInfo(_ message: String, duration: TimeInterval = 3.0) {
        show(.info, message: message, duration: duration)
    }

    /// Show a warning toast
    func showWarning(_ message: String, duration: TimeInterval = 3.0) {
        show(.warning, message: message, duration: duration)
        hapticNotification(type: .warning)
    }

    /// Show a message toast (NPC message notification)
    func showMessage(from sender: String, preview: String, duration: TimeInterval = 4.0, onTap: (() -> Void)? = nil) {
        let toast = ToastItem(type: .message, message: preview, duration: duration, title: sender, onTap: onTap)

        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }

            // Deduplicate: if a toast from the same sender is already showing or queued, replace it
            if let current = self.currentToast, current.type == .message, current.title == sender {
                self.currentToast = ToastItem(type: .message, message: preview, duration: duration, title: sender, onTap: onTap)
                return
            }
            if let queueIndex = self.toastQueue.firstIndex(where: { $0.type == .message && $0.title == sender }) {
                self.toastQueue[queueIndex] = toast
                return
            }

            if self.currentToast == nil {
                self.showToast(toast)
            } else {
                self.toastQueue.append(toast)
            }
        }

        hapticFeedback(style: .light)
    }

    /// Dismiss the current toast immediately
    func dismissCurrent() {
        timer?.invalidate()
        timer = nil

        withAnimation(AppAnimations.standard) {
            currentToast = nil
        }

        // Show next toast in queue after a brief delay
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
            self?.showNextInQueue()
        }
    }

    /// Clear all pending toasts
    func clearQueue() {
        toastQueue.removeAll()
    }

    // MARK: - Private Methods

    private func showToast(_ toast: ToastItem) {
        withAnimation(AppAnimations.standard) {
            currentToast = toast
        }

        // VoiceOver announcement
        UIAccessibility.post(notification: .announcement, argument: "\(toast.title ?? "") \(toast.message)")

        // Auto-dismiss after duration
        timer?.invalidate()
        timer = Timer.scheduledTimer(withTimeInterval: toast.duration, repeats: false) { [weak self] _ in
            self?.dismissCurrent()
        }
    }

    private func showNextInQueue() {
        guard currentToast == nil, !toastQueue.isEmpty else { return }
        let next = toastQueue.removeFirst()
        showToast(next)
    }
}

// MARK: - Toast Item
struct ToastItem: Identifiable, Equatable {
    let id = UUID()
    let type: ToastType
    let message: String
    let duration: TimeInterval
    let title: String?
    let onTap: (() -> Void)?

    init(type: ToastType, message: String, duration: TimeInterval = 3.0, title: String? = nil, onTap: (() -> Void)? = nil) {
        self.type = type
        self.message = message
        self.duration = duration
        self.title = title
        self.onTap = onTap
    }

    static func == (lhs: ToastItem, rhs: ToastItem) -> Bool {
        lhs.id == rhs.id
    }
}

// MARK: - Toast Overlay View
struct ToastOverlayView: View {
    @StateObject private var manager = ToastManager.shared

    var body: some View {
        VStack {
            if let toast = manager.currentToast {
                ManagedToastView(
                    type: toast.type,
                    message: toast.message,
                    title: toast.title,
                    onTap: toast.onTap,
                    onDismiss: {
                        manager.dismissCurrent()
                    }
                )
                .padding(.horizontal, AppSpacing.md)
                .padding(.top, AppSpacing.md)
                .transition(.move(edge: .top).combined(with: .opacity))
                .zIndex(1000)
            }

            Spacer()
        }
        .animation(AppAnimations.standard, value: manager.currentToast?.id)
    }
}

// MARK: - Managed Toast View (Internal)
private struct ManagedToastView: View {
    let type: ToastType
    let message: String
    let title: String?
    let onTap: (() -> Void)?
    let onDismiss: () -> Void

    @State private var dragOffset: CGFloat = 0

    init(type: ToastType, message: String, title: String? = nil, onTap: (() -> Void)? = nil, onDismiss: @escaping () -> Void) {
        self.type = type
        self.message = message
        self.title = title
        self.onTap = onTap
        self.onDismiss = onDismiss
    }

    var body: some View {
        HStack(spacing: AppSpacing.sm) {
            // Icon with soft glow background (matching ToastView cozy style)
            ZStack {
                Circle()
                    .fill(type.color.opacity(0.15))
                    .frame(width: 32, height: 32)

                Image(systemName: type.icon)
                    .foregroundColor(type.color)
                    .font(.system(size: 16, weight: .semibold))
            }
            .accessibilityHidden(true)

            VStack(alignment: .leading, spacing: 2) {
                if let title = title {
                    Text(title)
                        .font(.appBodyBold)
                        .foregroundColor(AppColors.primaryText)
                        .lineLimit(1)
                }

                Text(message)
                    .font(.appBody)
                    .foregroundColor(title != nil ? AppColors.secondaryText : AppColors.primaryText)
                    .lineLimit(2)
            }
            .accessibilityElement(children: .combine)

            Spacer()

            Button(action: onDismiss) {
                Image(systemName: "xmark.circle.fill")
                    .foregroundColor(AppColors.secondaryText.opacity(0.5))
                    .font(.system(size: 20))
            }
            .accessibilityLabel("Dismiss notification")
        }
        .padding(AppSpacing.md)
        .background(
            ZStack {
                RoundedRectangle(cornerRadius: AppSpacing.cornerRadius)
                    .fill(AppColors.cardBackground)

                RoundedRectangle(cornerRadius: AppSpacing.cornerRadius)
                    .fill(
                        LinearGradient(
                            colors: [
                                Color.white.opacity(0.8),
                                Color(hex: 0xFFF8F3).opacity(0.9)
                            ],
                            startPoint: .topLeading,
                            endPoint: .bottomTrailing
                        )
                    )
            }
        )
        .overlay(
            RoundedRectangle(cornerRadius: AppSpacing.cornerRadius)
                .stroke(type.color.opacity(0.2), lineWidth: 1.5)
        )
        .shadow(color: type.color.opacity(0.15), radius: 12, x: 0, y: 4)
        .shadow(color: .black.opacity(0.08), radius: 8, x: 0, y: 2)
        .offset(y: dragOffset)
        .gesture(
            DragGesture()
                .onChanged { value in
                    // Only allow upward drag
                    if value.translation.height < 0 {
                        dragOffset = value.translation.height
                    }
                }
                .onEnded { value in
                    if value.translation.height < -50 {
                        // Swipe up past threshold — dismiss
                        withAnimation(AppAnimations.standard) {
                            dragOffset = -200
                        }
                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                            onDismiss()
                        }
                    } else {
                        // Snap back
                        withAnimation(AppAnimations.standard) {
                            dragOffset = 0
                        }
                    }
                }
        )
        .contentShape(Rectangle())
        .onTapGesture {
            if let onTap = onTap {
                onTap()
                onDismiss()
            }
        }
        .accessibilityElement(children: .combine)
        .accessibilityAddTraits(onTap != nil ? .isButton : .isStaticText)
    }
}

// MARK: - Toast Modifier
extension View {
    /// Add toast overlay to your view hierarchy
    /// Add this at the root level of your app or main content view
    func toastOverlay() -> some View {
        ZStack {
            self

            ToastOverlayView()
        }
    }
}

// MARK: - Preview
#if DEBUG
struct ToastManager_Previews: PreviewProvider {
    static var previews: some View {
        VStack(spacing: AppSpacing.lg) {
            Button("Show Success") {
                ToastManager.shared.showSuccess("Payment successful!")
            }

            Button("Show Error") {
                ToastManager.shared.showError("Failed to connect to server")
            }

            Button("Show Warning") {
                ToastManager.shared.showWarning("Low energy remaining")
            }

            Button("Show Info") {
                ToastManager.shared.showInfo("New message from Sarah")
            }

            Button("Show Multiple") {
                ToastManager.shared.showSuccess("First toast")
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                    ToastManager.shared.showInfo("Second toast")
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                    ToastManager.shared.showWarning("Third toast")
                }
            }
        }
        .toastOverlay()
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(AppColors.background)
    }
}
#endif
