import SwiftUI
import SharedModels
import SwiftData

struct ClozeView: View {
    @Environment(\.modelContext) private var localContext
    @Environment(\.cloudModelContextProvider) private var cloudModelContextProvider

    @State private var questions: [ClozeQuestion] = []
    @State private var currentIndex = 0
    @State private var selectedOption: Int?
    @State private var correctCount = 0
    @State private var isFinished = false
    @State private var isLoading = true

    private var cloudContext: ModelContext { cloudModelContextProvider() }

    var body: some View {
        VStack(spacing: 20) {
            if isLoading {
                ProgressView("Loading questions...")
            } else if isFinished || questions.isEmpty {
                finishedView
            } else if let q = questions[safe: currentIndex] {
                questionView(q)
            }
        }
        .padding()
        .adaptiveContainer(maxWidth: 600)
        .navigationTitle("Cloze Practice")
        .navigationBarTitleDisplayMode(.inline)
        .onAppear(perform: loadQuestions)
    }

    // MARK: - Question View

    @ViewBuilder
    private func questionView(_ q: ClozeQuestion) -> some View {
        VStack(spacing: 20) {
            Text("\(currentIndex + 1) / \(questions.count)")
                .font(.caption.weight(.medium))
                .foregroundStyle(.secondary)

            ProgressView(value: Double(currentIndex), total: Double(questions.count))
                .tint(.indigo)

            // Sentence with blank
            Text(highlightedTemplate(q.displayTemplate))
                .font(.title3)
                .multilineTextAlignment(.center)
                .padding()
                .frame(maxWidth: .infinity)
                .background(.fill.quinary, in: RoundedRectangle(cornerRadius: 12))

            // English hint
            if !q.sentenceEN.isEmpty {
                Text(q.sentenceEN)
                    .font(.callout)
                    .foregroundStyle(.secondary)
                    .multilineTextAlignment(.center)
            }

            // Options
            VStack(spacing: 10) {
                ForEach(Array(q.options.enumerated()), id: \.offset) { index, option in
                    Button {
                        guard selectedOption == nil else { return }
                        selectedOption = index
                        if option.lowercased() == q.answer.lowercased() {
                            correctCount += 1
                        }
                    } label: {
                        HStack {
                            Text(option)
                                .font(.body)
                            Spacer()
                            if let selected = selectedOption {
                                if option.lowercased() == q.answer.lowercased() {
                                    Image(systemName: "checkmark.circle.fill").foregroundStyle(.green)
                                } else if index == selected {
                                    Image(systemName: "xmark.circle.fill").foregroundStyle(.red)
                                }
                            }
                        }
                        .padding()
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .background(optionBG(index: index, answer: q.answer, options: q.options), in: RoundedRectangle(cornerRadius: 10))
                    }
                    .buttonStyle(.plain)
                }
            }

            Spacer()

            if selectedOption != nil {
                Button {
                    if currentIndex + 1 < questions.count {
                        currentIndex += 1
                        selectedOption = nil
                    } else {
                        ReviewStore.recordActivity(context: cloudContext)
                        withAnimation { isFinished = true }
                    }
                } label: {
                    Text(currentIndex + 1 < questions.count ? "Next" : "See Results")
                        .font(.headline)
                        .frame(maxWidth: .infinity)
                        .padding(.vertical, 12)
                }
                .buttonStyle(.borderedProminent)
                .tint(.indigo)
            }
        }
    }

    // MARK: - Finished

    private var finishedView: some View {
        VStack(spacing: 20) {
            Spacer()
            Image(systemName: questions.isEmpty ? "text.badge.xmark" : "checkmark.circle")
                .font(.system(size: 60))
                .foregroundStyle(questions.isEmpty ? Color.secondary : Color.indigo)

            if questions.isEmpty {
                Text("No cloze questions available")
                    .font(.title3)
                    .foregroundStyle(.secondary)
                Text("Complete some course decks first to unlock cloze practice.")
                    .font(.subheadline)
                    .foregroundStyle(.tertiary)
                    .multilineTextAlignment(.center)
            } else {
                Text("\(correctCount) / \(questions.count)")
                    .font(.system(size: 48, weight: .bold).monospacedDigit())
                Text(correctCount == questions.count ? "Perfect!" : "Keep practicing!")
                    .font(.title3)
                    .foregroundStyle(.secondary)
            }
            Spacer()
        }
    }

    // MARK: - Helpers

    private func highlightedTemplate(_ template: String) -> AttributedString {
        var result = AttributedString(template)
        if let range = result.range(of: SentenceQuizEngine.blankMarker) {
            result[range].foregroundColor = .indigo
            result[range].font = .title3.bold()
        }
        return result
    }

    private func optionBG(index: Int, answer: String, options: [String]) -> some ShapeStyle {
        guard let selected = selectedOption else { return AnyShapeStyle(.fill.quaternary) }
        if options[index].lowercased() == answer.lowercased() { return AnyShapeStyle(.green.opacity(0.15)) }
        if index == selected { return AnyShapeStyle(.red.opacity(0.15)) }
        return AnyShapeStyle(.fill.quaternary)
    }

    private func loadQuestions() {
        let descriptor = FetchDescriptor<VocabCard>()
        let allCards = (try? localContext.fetch(descriptor)) ?? []
        let eligible = allCards.filter { SentenceQuizEngine.hasValidSentence(for: $0) }

        var result: [ClozeQuestion] = []
        let pool = eligible.shuffled().prefix(20)

        for card in pool {
            guard let q = SentenceQuizEngine.buildQuestion(for: card) else { continue }

            // Build distractors from other cards
            var distractors = eligible
                .filter { $0.front != card.front }
                .shuffled()
                .prefix(3)
                .map(\.front)

            while distractors.count < 3 {
                distractors.append("---")
            }

            var options = Array(distractors) + [q.blankWord]
            options.shuffle()

            result.append(ClozeQuestion(
                displayTemplate: q.displayTemplate,
                sentenceEN: q.sentenceEN,
                answer: q.blankWord,
                options: options
            ))

            if result.count >= 10 { break }
        }

        questions = result
        isLoading = false
    }
}

private struct ClozeQuestion {
    let displayTemplate: String
    let sentenceEN: String
    let answer: String
    let options: [String]
}

private extension Collection {
    subscript(safe index: Index) -> Element? {
        indices.contains(index) ? self[index] : nil
    }
}
