import SwiftUI

// MARK: - Loading Overlay View Modifier

/// A view modifier that displays a loading overlay on top of the content
struct LoadingOverlay: ViewModifier {
    let isLoading: Bool
    let message: String?

    func body(content: Content) -> some View {
        ZStack {
            content
                .disabled(isLoading)
                .blur(radius: isLoading ? 1 : 0)

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

                VStack(spacing: 12) {
                    ProgressView()
                        .progressViewStyle(CircularProgressViewStyle(tint: .white))
                        .scaleEffect(1.2)

                    if let message = message {
                        Text(message)
                            .foregroundColor(.white)
                            .font(.subheadline)
                            .multilineTextAlignment(.center)
                    }
                }
                .padding(24)
                .background(Color.black.opacity(0.7))
                .cornerRadius(12)
            }
        }
        .animation(.easeInOut(duration: 0.2), value: isLoading)
    }
}

// MARK: - View Extension

extension View {
    /// Apply a loading overlay to the view
    /// - Parameters:
    ///   - isLoading: Whether to show the loading overlay
    ///   - message: Optional message to display below the spinner
    func loadingOverlay(isLoading: Bool, message: String? = nil) -> some View {
        modifier(LoadingOverlay(isLoading: isLoading, message: message))
    }
}

// MARK: - Inline Loading View

/// A simple inline loading indicator
struct InlineLoadingView: View {
    let message: String?

    init(message: String? = nil) {
        self.message = message
    }

    var body: some View {
        HStack(spacing: 8) {
            ProgressView()

            if let message = message {
                Text(message)
                    .foregroundColor(Color.appTextSecondary)
                    .font(.subheadline)
            }
        }
    }
}

// MARK: - Button Loading State

/// A view modifier that shows loading state on a button
struct ButtonLoadingModifier: ViewModifier {
    let isLoading: Bool

    func body(content: Content) -> some View {
        content
            .opacity(isLoading ? 0 : 1)
            .overlay {
                if isLoading {
                    ProgressView()
                        .tint(.white)
                }
            }
            .disabled(isLoading)
    }
}

extension View {
    /// Apply loading state to a button
    func buttonLoading(_ isLoading: Bool) -> some View {
        modifier(ButtonLoadingModifier(isLoading: isLoading))
    }
}

// MARK: - Shimmer Loading Effect

/// A shimmer effect for loading placeholders
struct ShimmerModifier: ViewModifier {
    @State private var phase: CGFloat = 0
    @State private var isAnimating = false
    @Environment(\.accessibilityReduceMotion) private var reduceMotion

    func body(content: Content) -> some View {
        content
            .overlay(
                GeometryReader { geometry in
                    LinearGradient(
                        gradient: Gradient(colors: [
                            Color.clear,
                            Color.white.opacity(0.4),
                            Color.clear
                        ]),
                        startPoint: .leading,
                        endPoint: .trailing
                    )
                    .frame(width: geometry.size.width * 2)
                    .offset(x: -geometry.size.width + phase * geometry.size.width * 2)
                }
            )
            .mask(content)
            .onAppear {
                isAnimating = true
                guard !reduceMotion else {
                    phase = 0.5
                    return
                }
                withAnimation(.linear(duration: 1.5).repeatForever(autoreverses: false)) {
                    phase = 1
                }
            }
            .onDisappear {
                isAnimating = false
                phase = 0
            }
    }
}

extension View {
    /// Apply shimmer loading effect
    func shimmer() -> some View {
        modifier(ShimmerModifier())
    }
}

// MARK: - Skeleton Loading View

/// A skeleton placeholder view for loading states
struct SkeletonView: View {
    let width: CGFloat?
    let height: CGFloat

    init(width: CGFloat? = nil, height: CGFloat = 16) {
        self.width = width
        self.height = height
    }

    var body: some View {
        RoundedRectangle(cornerRadius: 4)
            .fill(Color.gray.opacity(0.3))
            .frame(width: width, height: height)
            .shimmer()
    }
}

// MARK: - Preview

#if DEBUG
struct LoadingOverlay_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            Text("Content behind loading overlay")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .loadingOverlay(isLoading: true, message: "Loading...")
    }
}
#endif
