//
//  View+LoadingError.swift
//  lichunWebsocket
//
//  View modifiers for loading and error states
//

import SwiftUI

extension View {
    /// Show loading overlay
    /// - Parameters:
    ///   - isLoading: Whether to show the loading overlay
    ///   - message: The message to display in the loading view
    /// - Returns: A view with the loading overlay applied
    func loading(_ isLoading: Bool, message: String = "Loading...") -> some View {
        ZStack {
            self

            if isLoading {
                Color.black.opacity(0.3)
                    .ignoresSafeArea()

                LoadingView(message: message)
                    .transition(.opacity)
            }
        }
        .animation(.easeInOut, value: isLoading)
    }

    /// Show error overlay with recovery options
    /// - Parameters:
    ///   - error: Binding to the current error (set to nil to dismiss)
    ///   - onRetry: Optional retry action
    /// - Returns: A view with the error overlay applied
    func errorOverlay(
        error: Binding<WebSocketService.WebSocketError?>,
        onRetry: (() -> Void)? = nil
    ) -> some View {
        ZStack {
            self

            if let currentError = error.wrappedValue {
                Color.black.opacity(0.5)
                    .ignoresSafeArea()
                    .transition(.opacity)
                    .onTapGesture {
                        // Dismiss on background tap
                        error.wrappedValue = nil
                    }

                ErrorRecoveryView(
                    error: currentError,
                    onRetry: onRetry,
                    onDismiss: {
                        error.wrappedValue = nil
                    }
                )
                .padding(AppSpacing.xl)
                .transition(.scale.combined(with: .opacity))
            }
        }
        .animation(.spring(response: 0.4, dampingFraction: 0.8), value: error.wrappedValue?.id)
    }

    /// Show error banner at the top of the view (less intrusive)
    /// - Parameters:
    ///   - error: Binding to the current error (set to nil to dismiss)
    ///   - autoDismiss: Whether to auto-dismiss the banner after a delay
    ///   - dismissDelay: The delay before auto-dismissing (default: 3 seconds)
    /// - Returns: A view with the error banner applied
    func errorBanner(
        error: Binding<WebSocketService.WebSocketError?>,
        autoDismiss: Bool = true,
        dismissDelay: TimeInterval = 3.0
    ) -> some View {
        ZStack(alignment: .top) {
            self

            if let currentError = error.wrappedValue {
                ErrorBanner(
                    error: currentError,
                    onDismiss: {
                        error.wrappedValue = nil
                    }
                )
                .padding(.horizontal, AppSpacing.md)
                .padding(.top, AppSpacing.md)
                .zIndex(999)
                .onAppear {
                    if autoDismiss {
                        DispatchQueue.main.asyncAfter(deadline: .now() + dismissDelay) {
                            if error.wrappedValue?.id == currentError.id {
                                error.wrappedValue = nil
                            }
                        }
                    }
                }
            }
        }
        .animation(.spring(response: 0.4, dampingFraction: 0.8), value: error.wrappedValue?.id)
    }

    /// Show progress loading overlay
    /// - Parameters:
    ///   - isLoading: Whether to show the progress loading
    ///   - message: The message to display
    ///   - progress: Binding to the current progress (0.0 to 1.0)
    /// - Returns: A view with the progress loading overlay applied
    func progressLoading(
        _ isLoading: Bool,
        message: String = "Loading...",
        progress: Binding<Double>
    ) -> some View {
        ZStack {
            self

            if isLoading {
                Color.black.opacity(0.3)
                    .ignoresSafeArea()

                ProgressLoadingView(message: message, progress: progress)
                    .transition(.scale.combined(with: .opacity))
            }
        }
        .animation(.easeInOut, value: isLoading)
    }

    /// Show skeleton loading state
    /// - Parameters:
    ///   - isLoading: Whether to show skeleton loaders
    ///   - skeletonCount: Number of skeleton items to show
    /// - Returns: A view with skeleton loaders or the actual content
    func skeleton(_ isLoading: Bool, skeletonCount: Int = 3) -> some View {
        LoadingStateView(isLoading: isLoading, skeletonCount: skeletonCount) {
            self
        }
    }
}

// MARK: - Preview
#if DEBUG
struct ViewLoadingError_Previews: PreviewProvider {
    @State static var isLoading = true
    @State static var error: WebSocketService.WebSocketError? = .connectionLost
    @State static var progress: Double = 0.5

    static var previews: some View {
        ZStack {
            AppColors.background
                .ignoresSafeArea()

            VStack(spacing: AppSpacing.xl) {
                Text("View Modifiers Demo")
                    .font(.appLargeTitle)
                    .foregroundColor(AppColors.primaryText)

                // Sample content
                VStack(spacing: AppSpacing.md) {
                    ForEach(0..<3) { i in
                        HStack {
                            Circle()
                                .fill(AppColors.primary)
                                .frame(width: 40, height: 40)

                            VStack(alignment: .leading) {
                                Text("Item \(i + 1)")
                                    .font(.appHeadline)
                                    .foregroundColor(AppColors.primaryText)

                                Text("Description")
                                    .font(.appCaption)
                                    .foregroundColor(AppColors.secondaryText)
                            }

                            Spacer()
                        }
                        .padding(AppSpacing.md)
                        .background(AppColors.cardBackground)
                        .cornerRadius(AppSpacing.cornerRadius)
                    }
                }
                .padding()
            }
        }
        // Uncomment to test different modifiers:
        // .loading(true, message: "Loading content...")
        // .errorOverlay(error: .constant(.connectionLost), onRetry: { print("Retry") })
        // .errorBanner(error: .constant(.serverError(message: "Test error")))
        // .progressLoading(true, message: "Uploading...", progress: .constant(0.65))
        // .skeleton(true, skeletonCount: 3)
    }
}
#endif
