import SwiftUI

// MARK: - Branded loading spinner

struct ZXLoadingView: View {
    let size: CGFloat
    let lineWidth: CGFloat

    init(size: CGFloat = 36, lineWidth: CGFloat = 3) {
        self.size = size
        self.lineWidth = lineWidth
    }

    @State private var rotation: Double = 0

    var body: some View {
        ZStack {
            // rotating gradient arc
            Circle()
                .trim(from: 0.05, to: 0.8)
                .stroke(
                    AngularGradient(
                        colors: [Color(hex: "#7C6EFA"), Color(hex: "#A78BFA"), Color(hex: "#F97316"), Color(hex: "#7C6EFA")],
                        center: .center,
                        startAngle: .degrees(rotation),
                        endAngle: .degrees(rotation + 300)
                    ),
                    style: StrokeStyle(lineWidth: lineWidth, lineCap: .round)
                )
                .frame(width: size, height: size)
                .rotationEffect(.degrees(rotation))

            // center dot
            Circle()
                .fill(Color(hex: "#7C6EFA", opacity: 0.3))
                .frame(width: size * 0.3, height: size * 0.3)
        }
        .onAppear {
            withAnimation(.linear(duration: 1.2).repeatForever(autoreverses: false)) {
                rotation = 360
            }
        }
    }
}

// MARK: - Full-screen loading overlay

struct ZXLoadingOverlay: View {
    let message: String?

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

    var body: some View {
        ZStack {
            Color.black.opacity(0.35).ignoresSafeArea()
            VStack(spacing: 16) {
                ZXLoadingView(size: 44, lineWidth: 3.5)
                if let message {
                    Text(message)
                        .font(.system(size: 14, weight: .medium))
                        .foregroundColor(Color.zxF04)
                }
            }
            .padding(28)
            .background(
                RoundedRectangle(cornerRadius: 20)
                    .fill(.ultraThinMaterial)
            )
        }
    }
}

// MARK: - Skeleton shimmer (for placeholder loading)

struct ZXShimmer: ViewModifier {
    @Environment(\.colorScheme) private var colorScheme
    @Environment(\.accessibilityReduceMotion) private var reduceMotion
    @State private var phase: CGFloat = -0.5

    private var shimmerColor: Color {
        colorScheme == .dark ? Color.white.opacity(0.06) : Color.black.opacity(0.06)
    }

    func body(content: Content) -> some View {
        content
            .overlay(
                LinearGradient(
                    colors: [
                        shimmerColor.opacity(0),
                        shimmerColor,
                        shimmerColor.opacity(0),
                    ],
                    startPoint: .leading,
                    endPoint: .trailing
                )
                .rotationEffect(.degrees(15))
                .scaleEffect(2)
                .offset(x: phase * 400)
                .animation(reduceMotion ? nil : .linear(duration: 1.5).repeatForever(autoreverses: false), value: phase)
            )
            .clipped()
            .onAppear { phase = reduceMotion ? 0 : 1.5 }
    }
}

extension View {
    func zxShimmer() -> some View {
        modifier(ZXShimmer())
    }
}

// MARK: - Staggered dot loader (for inline use, e.g. AI thinking)

struct ZXDotLoader: View {
    @State private var step = 0
    let color: Color

    init(color: Color = Color.zxPurple) {
        self.color = color
    }

    var body: some View {
        HStack(spacing: 6) {
            ForEach(0..<3, id: \.self) { i in
                Circle()
                    .fill(color)
                    .frame(width: 8, height: 8)
                    .scaleEffect(step == i ? 1.2 : 0.7)
                    .opacity(step == i ? 1 : 0.4)
                    .animation(.easeInOut(duration: 0.4), value: step)
            }
        }
        .onAppear {
            Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
                step = (step + 1) % 3
            }
        }
    }
}
