import SwiftUI

struct B4ProgressView: View {
    var onComplete: () -> Void

    @State private var step: Int = 1
    @State private var pulse = false
    @State private var glow = false
    @State private var rotate: Double = 0
    @State private var elapsed: Double = 0.2

    private let lineLabels = [
        String(appLoc: "正在本地识别第 1 / 3 页…"),
        String(appLoc: "正在本地识别第 2 / 3 页…"),
        String(appLoc: "正在本地识别第 3 / 3 页…"),
        String(appLoc: "提取指标 · 共 28 项"),
        String(appLoc: "生成整体摘要…"),
    ]

    var body: some View {
        ZStack {
            backgroundGradient.ignoresSafeArea()

            VStack(spacing: 0) {
                Spacer()
                chip.padding(.bottom, 36)

                Text("本地 AI · 正在解读")
                    .font(.system(size: 22, weight: .semibold))
                    .tracking(1)
                    .foregroundStyle(Color.white.opacity(0.95))
                    .padding(.bottom, 6)

                Text("QWEN2.5-VL · ON-DEVICE · SME2")
                    .font(.system(size: 11, design: .monospaced))
                    .tracking(0.5)
                    .foregroundStyle(Color.white.opacity(0.55))
                    .padding(.bottom, 30)

                lineList
                    .padding(.horizontal, 28)

                speedBadge.padding(.top, 32)
                Spacer()

                Text("本地处理中 · 不会上传任何内容")
                    .font(.system(size: 10, design: .monospaced))
                    .tracking(0.5)
                    .foregroundStyle(Color.white.opacity(0.45))
                    .padding(.bottom, 30)
            }
            .padding(.horizontal, 28)
        }
        .preferredColorScheme(.dark)
        .onAppear { startAnimations() }
    }

    private var backgroundGradient: some View {
        RadialGradient(
            colors: [
                Color(red: 0.22, green: 0.21, blue: 0.18),
                Color(red: 0.13, green: 0.12, blue: 0.10),
                Color(red: 0.08, green: 0.075, blue: 0.06),
            ],
            center: .init(x: 0.5, y: 0.3),
            startRadius: 60,
            endRadius: 700
        )
    }

    private var chip: some View {
        ZStack {
            Circle()
                .fill(Color(red: 0.93, green: 0.75, blue: 0.40).opacity(glow ? 0.18 : 0.0))
                .frame(width: 176, height: 176)
                .blur(radius: 30)

            Circle()
                .strokeBorder(Color.white.opacity(0.18),
                              style: StrokeStyle(lineWidth: 1, dash: [4, 4]))
                .frame(width: 140, height: 140)
                .rotationEffect(.degrees(rotate))

            RoundedRectangle(cornerRadius: 22, style: .continuous)
                .fill(
                    LinearGradient(
                        colors: [Color(red: 0.36, green: 0.34, blue: 0.30),
                                 Color(red: 0.22, green: 0.21, blue: 0.18)],
                        startPoint: .topLeading, endPoint: .bottomTrailing
                    )
                )
                .overlay(
                    RoundedRectangle(cornerRadius: 22, style: .continuous)
                        .strokeBorder(Color.white.opacity(0.10), lineWidth: 1)
                )
                .frame(width: 96, height: 96)
                .shadow(color: .black.opacity(0.4), radius: 20, x: 0, y: 12)
                .overlay(ChipGlyph())
                .overlay(alignment: .topTrailing) {
                    Circle()
                        .fill(Color(red: 0.95, green: 0.78, blue: 0.40))
                        .frame(width: 6, height: 6)
                        .opacity(pulse ? 1 : 0.35)
                        .shadow(color: Color(red: 0.95, green: 0.78, blue: 0.40), radius: 6)
                        .padding(10)
                }
                .scaleEffect(pulse ? 1.06 : 1.0)
                .opacity(pulse ? 0.92 : 1.0)
        }
    }

    private var lineList: some View {
        VStack(alignment: .leading, spacing: 10) {
            ForEach(Array(lineLabels.enumerated()), id: \.offset) { idx, label in
                LineRow(
                    text: label,
                    done: step > idx + 1,
                    active: step == idx + 1,
                    isLast: idx == lineLabels.count - 1
                )
                .opacity(step >= idx + 1 ? 1 : 0)
                .offset(y: step >= idx + 1 ? 0 : 6)
                .animation(.easeOut(duration: 0.4).delay(Double(idx) * 0.05), value: step)
            }
        }
        .frame(maxWidth: .infinity, alignment: .leading)
    }

    private var speedBadge: some View {
        Text(String(format: String(appLoc: "已处理 %.1fs · 比云端快 4.2×"), elapsed))
            .font(.system(size: 10, design: .monospaced))
            .tracking(0.6)
            .foregroundStyle(Color.white.opacity(0.75))
            .padding(.horizontal, 12)
            .padding(.vertical, 6)
            .background(Capsule().fill(Color.white.opacity(0.08)))
    }

    private func startAnimations() {
        withAnimation(.easeInOut(duration: 2.0).repeatForever(autoreverses: true)) {
            pulse.toggle()
        }
        withAnimation(.easeInOut(duration: 2.4).repeatForever(autoreverses: true)) {
            glow.toggle()
        }
        withAnimation(.linear(duration: 14).repeatForever(autoreverses: false)) {
            rotate = 360
        }

        Task {
            for _ in 0..<lineLabels.count {
                try? await Task.sleep(nanoseconds: 900_000_000)
                await MainActor.run {
                    withAnimation { step += 1 }
                    elapsed += 0.9
                }
            }
            try? await Task.sleep(nanoseconds: 600_000_000)
            await MainActor.run { onComplete() }
        }
    }
}

private struct LineRow: View {
    let text: String
    let done: Bool
    let active: Bool
    let isLast: Bool

    @State private var dotPulse = false

    var body: some View {
        HStack(spacing: 10) {
            ZStack {
                Circle()
                    .fill(done
                          ? Color(red: 0.95, green: 0.78, blue: 0.40)
                          : Color.white.opacity(0.12))
                if done {
                    Image(systemName: "checkmark")
                        .font(.system(size: 8, weight: .bold))
                        .foregroundStyle(Color(red: 0.10, green: 0.115, blue: 0.094))
                }
            }
            .frame(width: 14, height: 14)

            Text(text)
                .font(.system(size: 13))
                .foregroundStyle(done ? Color.white.opacity(0.95) : Color.white.opacity(0.45))

            if active {
                Spacer()
                Text("···")
                    .font(.system(size: 10, design: .monospaced))
                    .foregroundStyle(Color.white.opacity(dotPulse ? 0.9 : 0.4))
                    .onAppear {
                        withAnimation(.easeInOut(duration: 1.0).repeatForever(autoreverses: true)) {
                            dotPulse.toggle()
                        }
                    }
            }
        }
    }
}

private struct ChipGlyph: View {
    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 5, style: .continuous)
                .strokeBorder(Color.white.opacity(0.8), lineWidth: 1.4)
                .frame(width: 28, height: 28)

            RoundedRectangle(cornerRadius: 2, style: .continuous)
                .fill(Color(red: 0.95, green: 0.78, blue: 0.40).opacity(0.35))
                .overlay(
                    RoundedRectangle(cornerRadius: 2, style: .continuous)
                        .strokeBorder(Color(red: 0.95, green: 0.78, blue: 0.40), lineWidth: 1)
                )
                .frame(width: 16, height: 16)

            innerCross
            outerPins
        }
        .frame(width: 56, height: 56)
    }

    private var innerCross: some View {
        Canvas { ctx, size in
            let amber = Color(red: 0.95, green: 0.78, blue: 0.40)
            let stroke = GraphicsContext.Shading.color(amber)
            let cx = size.width / 2
            let cy = size.height / 2

            let pairs: [(CGPoint, CGPoint)] = [
                (CGPoint(x: cx, y: cy - 8), CGPoint(x: cx, y: cy - 4)),
                (CGPoint(x: cx, y: cy + 4), CGPoint(x: cx, y: cy + 8)),
                (CGPoint(x: cx - 8, y: cy), CGPoint(x: cx - 4, y: cy)),
                (CGPoint(x: cx + 4, y: cy), CGPoint(x: cx + 8, y: cy)),
            ]
            for (s, e) in pairs {
                var p = Path()
                p.move(to: s)
                p.addLine(to: e)
                ctx.stroke(p, with: stroke, style: StrokeStyle(lineWidth: 1, lineCap: .round))
            }
        }
        .frame(width: 56, height: 56)
    }

    private var outerPins: some View {
        Canvas { ctx, size in
            let pinColor = GraphicsContext.Shading.color(Color.white.opacity(0.45))
            let cx = size.width / 2
            let cy = size.height / 2
            let halfChip: CGFloat = 14
            let outsideStart: CGFloat = 20
            let outsideEnd: CGFloat = 26

            let positions: [CGFloat] = [-8, 0, 8]

            for offset in positions {
                // top
                var p = Path()
                p.move(to: CGPoint(x: cx + offset, y: cy - outsideEnd))
                p.addLine(to: CGPoint(x: cx + offset, y: cy - halfChip))
                ctx.stroke(p, with: pinColor, style: StrokeStyle(lineWidth: 1, lineCap: .round))

                // bottom
                p = Path()
                p.move(to: CGPoint(x: cx + offset, y: cy + halfChip))
                p.addLine(to: CGPoint(x: cx + offset, y: cy + outsideEnd))
                ctx.stroke(p, with: pinColor, style: StrokeStyle(lineWidth: 1, lineCap: .round))

                // left
                p = Path()
                p.move(to: CGPoint(x: cx - outsideEnd, y: cy + offset))
                p.addLine(to: CGPoint(x: cx - halfChip, y: cy + offset))
                ctx.stroke(p, with: pinColor, style: StrokeStyle(lineWidth: 1, lineCap: .round))

                // right
                p = Path()
                p.move(to: CGPoint(x: cx + halfChip, y: cy + offset))
                p.addLine(to: CGPoint(x: cx + outsideStart + 2, y: cy + offset))
                ctx.stroke(p, with: pinColor, style: StrokeStyle(lineWidth: 1, lineCap: .round))
            }
        }
        .frame(width: 56, height: 56)
    }
}

#Preview {
    B4ProgressView(onComplete: {})
}
