import SwiftUI
import SharedModels
import SwiftData

struct CheckpointExamView: View {
    let courseName: String
    let throughWeek: Int

    @Environment(\.modelContext) private var modelContext
    @Environment(\.cloudModelContextProvider) private var cloudModelContextProvider
    @Query private var allDecks: [CourseDeck]

    @State private var cardsByWeek: [Int: [VocabCard]] = [:]
    @State private var checkpointResults: [TestResult] = []
    @State private var selectedCount = 25

    private let questionCounts = [25, 50, 100]

    private var cloudModelContext: ModelContext { cloudModelContextProvider() }

    private var totalAvailable: Int {
        cardsByWeek.values.reduce(0) { $0 + $1.count }
    }

    /// Sample evenly across weeks, then fill remainder round-robin.
    private var sampledCards: [VocabCard] {
        let weekNumbers = cardsByWeek.keys.sorted()
        guard !weekNumbers.isEmpty else { return [] }

        let target = min(selectedCount, totalAvailable)
        let perWeek = target / weekNumbers.count
        var remainder = target - (perWeek * weekNumbers.count)

        var result: [VocabCard] = []
        for week in weekNumbers {
            guard let pool = cardsByWeek[week] else { continue }
            let shuffled = pool.shuffled()
            var take = min(perWeek, shuffled.count)
            // Distribute remainder one extra card per week until exhausted
            if remainder > 0 && take < shuffled.count {
                take += 1
                remainder -= 1
            }
            result.append(contentsOf: shuffled.prefix(take))
        }

        // If some weeks had fewer cards than perWeek, fill from weeks with surplus
        if result.count < target {
            let used = Set(result.map { ObjectIdentifier($0) })
            var extras: [VocabCard] = []
            for week in weekNumbers {
                guard let pool = cardsByWeek[week] else { continue }
                extras.append(contentsOf: pool.filter { !used.contains(ObjectIdentifier($0)) })
            }
            extras.shuffle()
            result.append(contentsOf: extras.prefix(target - result.count))
        }

        return result.shuffled()
    }

    var body: some View {
        ScrollView {
            VStack(spacing: 24) {
                VStack(spacing: 4) {
                    Image(systemName: "checkmark.seal")
                        .font(.system(size: 44))
                        .foregroundStyle(.blue)
                    Text("Checkpoint Exam")
                        .font(.largeTitle.weight(.bold))
                    Text("Weeks 1–\(throughWeek)")
                        .font(.subheadline)
                        .foregroundStyle(.secondary)
                }
                .padding(.top, 8)

                // Question count picker
                VStack(spacing: 8) {
                    Text("Questions")
                        .font(.subheadline.weight(.medium))
                        .foregroundStyle(.secondary)

                    HStack(spacing: 12) {
                        ForEach(questionCounts, id: \.self) { count in
                            let available = count <= totalAvailable
                            Button {
                                withAnimation { selectedCount = count }
                            } label: {
                                Text("\(count)")
                                    .font(.headline)
                                    .frame(maxWidth: .infinity)
                                    .padding(.vertical, 10)
                            }
                            .buttonStyle(.bordered)
                            .tint(selectedCount == count ? .blue : .secondary)
                            .disabled(!available)
                            .opacity(available ? 1 : 0.4)
                        }
                    }
                    .padding(.horizontal)
                }

                VStack(spacing: 8) {
                    Label("Multiple choice", systemImage: "list.bullet")
                    Label("Cumulative vocabulary", systemImage: "books.vertical")
                    Label("\(totalAvailable) words available", systemImage: "character.book.closed")
                }
                .font(.subheadline)
                .foregroundStyle(.secondary)

                if cardsByWeek.isEmpty {
                    ProgressView("Loading vocabulary...")
                        .padding(.top, 20)
                } else {
                    NavigationLink {
                        CourseQuizView(
                            cards: sampledCards,
                            quizType: .checkpoint,
                            courseName: courseName,
                            weekNumber: throughWeek,
                            isFocusMode: false
                        )
                    } label: {
                        Text("Begin Exam")
                            .font(.headline)
                            .frame(maxWidth: .infinity)
                            .padding(.vertical, 12)
                    }
                    .buttonStyle(.borderedProminent)
                    .tint(.blue)
                    .padding(.horizontal)
                }

                // Score History
                if !checkpointResults.isEmpty {
                    VStack(alignment: .leading, spacing: 12) {
                        Text("Score History")
                            .font(.headline)
                            .padding(.horizontal)

                        VStack(spacing: 0) {
                            ForEach(Array(checkpointResults.prefix(10).enumerated()), id: \.offset) { _, result in
                                HStack {
                                    Text(result.dateTaken.formatted(date: .abbreviated, time: .shortened))
                                        .font(.subheadline)
                                        .foregroundStyle(.secondary)

                                    Spacer()

                                    VStack(alignment: .trailing, spacing: 2) {
                                        Text("\(result.scorePercent)%")
                                            .font(.title3.weight(.bold))
                                            .foregroundStyle(scoreColor(result.scorePercent))
                                        Text("\(result.correctCount)/\(result.totalQuestions)")
                                            .font(.caption)
                                            .foregroundStyle(.secondary)
                                    }
                                }
                                .padding(.horizontal, 14)
                                .padding(.vertical, 10)
                                Divider().padding(.leading, 14)
                            }
                        }
                        .background(.fill.quinary, in: RoundedRectangle(cornerRadius: 12))
                        .padding(.horizontal)
                    }
                }
            }
            .padding(.vertical)
            .adaptiveContainer()
        }
        .navigationTitle("Checkpoint")
        .navigationBarTitleDisplayMode(.inline)
        .onAppear {
            loadCumulativeCards()
            loadResults()
        }
    }

    private func loadCumulativeCards() {
        let course = courseName
        let maxWeek = throughWeek
        let weekDecks = allDecks.filter {
            $0.courseName == course && $0.weekNumber <= maxWeek && !$0.isReversed
        }
        var grouped: [Int: [VocabCard]] = [:]
        for deck in weekDecks {
            let deckId = deck.id
            let descriptor = FetchDescriptor<VocabCard>(
                predicate: #Predicate<VocabCard> { $0.deckId == deckId }
            )
            if let fetched = try? modelContext.fetch(descriptor) {
                grouped[deck.weekNumber, default: []].append(contentsOf: fetched)
            }
        }
        cardsByWeek = grouped
    }

    private func loadResults() {
        let course = courseName
        let week = throughWeek
        let checkpointType = QuizType.checkpoint.rawValue
        let descriptor = FetchDescriptor<TestResult>(
            predicate: #Predicate<TestResult> {
                $0.courseName == course && $0.weekNumber == week && $0.quizType == checkpointType
            },
            sortBy: [SortDescriptor(\TestResult.dateTaken, order: .reverse)]
        )
        checkpointResults = (try? cloudModelContext.fetch(descriptor)) ?? []
    }

    private func scoreColor(_ percent: Int) -> Color {
        if percent >= 90 { return .green }
        if percent >= 70 { return .orange }
        return .red
    }
}

#Preview {
    NavigationStack {
        CheckpointExamView(courseName: "LanGo Spanish | Beginner I", throughWeek: 3)
    }
    .modelContainer(for: [TestResult.self, CourseDeck.self, VocabCard.self], inMemory: true)
}
