import SwiftUI
import SharedModels
import SwiftData
import PencilKit

/// Practice mode where user fills in all 6 person conjugations for a verb + tense.
struct FullTableView: View {
    @Environment(\.modelContext) private var modelContext
    @Environment(\.cloudModelContextProvider) private var cloudModelContextProvider
    let speechService: SpeechService

    @State private var currentVerb: Verb?
    @State private var currentTense: TenseInfo?
    @State private var correctForms: [VerbForm] = []
    @State private var userAnswers: [String] = Array(repeating: "", count: 6)
    @State private var results: [Bool?] = Array(repeating: nil, count: 6)
    @State private var isChecked = false
    @State private var showVosotros = true
    @State private var autoFillStem = false
    @State private var useHandwriting = false
    @State private var sessionCount = 0
    @State private var sessionCorrect = 0
    @State private var noEligibleVerbs = false

    // Handwriting state per field
    @State private var drawings: [PKDrawing] = Array(repeating: PKDrawing(), count: 6)
    @State private var activeHWField: Int?
    @State private var isRecognizing = false

    @FocusState private var focusedField: Int?

    private let persons = TenseInfo.persons
    private var cloudModelContext: ModelContext { cloudModelContextProvider() }

    private var personsToShow: [(index: Int, label: String)] {
        persons.enumerated().compactMap { index, label in
            if !showVosotros && index == 4 { return nil }
            return (index, label)
        }
    }

    /// Get the stem of the current verb (infinitive minus ending)
    private var verbStem: String {
        guard let verb = currentVerb else { return "" }
        let inf = verb.infinitive.lowercased()
        if inf.hasSuffix("ar") || inf.hasSuffix("er") || inf.hasSuffix("ir") {
            return String(inf.dropLast(2))
        }
        if inf.hasSuffix("ír") {
            return String(inf.dropLast(2))
        }
        return inf
    }

    var body: some View {
        ScrollView {
            if noEligibleVerbs {
                emptyPoolError
            } else {
                VStack(spacing: 32) {
                    // Header
                    if let verb = currentVerb, let tense = currentTense {
                        headerSection(verb: verb, tense: tense)
                    }

                    // Input mode toggle
                    HStack {
                        Picker("Input", selection: $useHandwriting) {
                            Label("Keyboard", systemImage: "keyboard").tag(false)
                            Label("Pencil", systemImage: "pencil.and.outline").tag(true)
                        }
                        .pickerStyle(.segmented)
                    }
                    .padding(.horizontal)

                    // Input fields
                    inputSection

                    // Check / Next button
                    actionButton

                    // Score
                    if sessionCount > 0 {
                        scoreSection
                    }
                }
                .padding()
                .adaptiveContainer()
            }
        }
        .navigationTitle("Full Table")
        .navigationBarTitleDisplayMode(.inline)
        .onAppear {
            loadSettings()
            loadNextVerb()
        }
    }

    // MARK: - Empty pool error

    private var emptyPoolError: some View {
        VStack(spacing: 16) {
            ContentUnavailableView(
                "No regular verbs available",
                systemImage: "exclamationmark.triangle",
                description: Text(
                    "None of the selected tenses have any fully-regular verbs in the current settings. Enable more tenses, or turn off the Reflexive-only toggle in Settings."
                )
            )
        }
        .padding()
        .adaptiveContainer()
    }

    // MARK: - Header

    private func headerSection(verb: Verb, tense: TenseInfo) -> some View {
        VStack(spacing: 8) {
            Text(verb.infinitive)
                .font(.largeTitle.weight(.bold))

            Button {
                speechService.speak(verb.infinitive)
            } label: {
                Image(systemName: "speaker.wave.2")
                    .font(.title3)
            }
            .tint(.secondary)

            Text(verb.english)
                .font(.title3)
                .foregroundStyle(.secondary)

            TensePill(tenseInfo: tense)
        }
        .padding(.top, 8)
    }

    // MARK: - Input Fields

    private var inputSection: some View {
        VStack(spacing: 16) {
            ForEach(personsToShow, id: \.index) { index, label in
                VStack(spacing: 4) {
                    HStack(spacing: 12) {
                        Text(label)
                            .font(.subheadline.weight(.medium))
                            .foregroundStyle(.secondary)
                            .frame(minWidth: 90, alignment: .trailing)

                        if useHandwriting {
                            // Handwriting canvas per field
                            ZStack(alignment: .trailing) {
                                VStack(spacing: 0) {
                                    if autoFillStem {
                                        Text(verbStem)
                                            .font(.caption)
                                            .foregroundStyle(.tertiary)
                                            .frame(maxWidth: .infinity, alignment: .leading)
                                    }
                                    HandwritingCanvas(drawing: $drawings[index])
                                        .frame(height: 60)
                                        .disabled(isChecked)
                                }
                                .background(.fill.quinary, in: RoundedRectangle(cornerRadius: 10))
                                .overlay(
                                    RoundedRectangle(cornerRadius: 10)
                                        .stroke(dividerColor(for: index), lineWidth: 1)
                                )

                                if let result = results[index] {
                                    Image(systemName: result ? "checkmark.circle.fill" : "xmark.circle.fill")
                                        .foregroundStyle(result ? .green : .red)
                                        .font(.title3)
                                        .padding(.trailing, 8)
                                }
                            }
                        } else {
                            // Keyboard text field
                            ZStack(alignment: .trailing) {
                                TextField(autoFillStem ? verbStem : "", text: $userAnswers[index])
                                    .font(.title3)
                                    .textInputAutocapitalization(.never)
                                    .autocorrectionDisabled()
                                    .focused($focusedField, equals: index)
                                    .disabled(isChecked)
                                    .onSubmit { advanceFocus(from: index) }
                                    .foregroundStyle(foregroundColor(for: index))

                                if let result = results[index] {
                                    Image(systemName: result ? "checkmark.circle.fill" : "xmark.circle.fill")
                                        .foregroundStyle(result ? .green : .red)
                                        .font(.title3)
                                }
                            }

                            Divider()
                                .frame(height: 1)
                                .overlay(dividerColor(for: index))
                        }
                    }

                    // Show correct answer if wrong
                    if isChecked, let result = results[index], !result {
                        HStack {
                            Spacer()
                                .frame(minWidth: 102)
                            Text(correctForms.first(where: { $0.personIndex == index })?.form ?? "")
                                .font(.callout.weight(.medium))
                                .foregroundStyle(.green)
                        }
                    }
                }
            }
        }
        .padding()
        .glassEffect(in: RoundedRectangle(cornerRadius: 20))
    }

    // MARK: - Action Button

    private var actionButton: some View {
        Button {
            if isChecked {
                loadNextVerb()
            } else {
                if useHandwriting {
                    recognizeAndCheck()
                } else {
                    checkAnswers()
                }
            }
        } label: {
            HStack {
                if isRecognizing {
                    ProgressView().tint(.white)
                }
                Text(isChecked ? "Next" : "Check")
                    .font(.headline)
            }
            .frame(maxWidth: .infinity)
            .padding(.vertical, 14)
        }
        .buttonStyle(.borderedProminent)
        .tint(isChecked ? .blue : .orange)
        .disabled(isRecognizing)
    }

    // MARK: - Score

    private var scoreSection: some View {
        HStack(spacing: 20) {
            Label("\(sessionCount) reviewed", systemImage: "square.stack")
            Label("\(sessionCorrect) perfect", systemImage: "checkmark.seal")
        }
        .font(.caption)
        .foregroundStyle(.secondary)
    }

    // MARK: - Logic

    private func loadNextVerb() {
        isChecked = false
        results = Array(repeating: nil, count: 6)
        correctForms = []
        drawings = Array(repeating: PKDrawing(), count: 6)
        let service = PracticeSessionService(
            localContext: modelContext,
            cloudContext: cloudModelContext,
            reflexiveBaseInfinitives: ReflexiveVerbStore.shared.baseInfinitives
        )
        guard let prompt = service.randomFullTablePrompt(
            previousTenseId: currentTense?.id,
            previousEnding: currentVerb?.ending
        ) else {
            // Genuinely no eligible (verb, tense) combo. Surface a clear error
            // instead of a blank screen — the previous behaviour silently
            // rendered an empty header and inputs.
            currentVerb = nil
            currentTense = nil
            userAnswers = Array(repeating: "", count: 6)
            focusedField = nil
            noEligibleVerbs = true
            return
        }

        noEligibleVerbs = false
        currentVerb = prompt.verb
        currentTense = prompt.tenseInfo
        correctForms = prompt.forms

        // Auto-fill stems if enabled
        if autoFillStem {
            let stem = verbStem
            userAnswers = Array(repeating: stem, count: 6)
        } else {
            userAnswers = Array(repeating: "", count: 6)
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            if !useHandwriting {
                focusedField = personsToShow.first?.index ?? 0
            }
        }
    }

    private func recognizeAndCheck() {
        isRecognizing = true
        Task {
            for person in personsToShow {
                let idx = person.index
                let result = await HandwritingRecognizer.recognize(drawing: drawings[idx])
                var recognized = result.text
                // Prepend stem if auto-fill is on
                if autoFillStem && !recognized.isEmpty {
                    recognized = verbStem + recognized
                }
                await MainActor.run {
                    userAnswers[idx] = recognized
                }
            }
            await MainActor.run {
                isRecognizing = false
                checkAnswers()
            }
        }
    }

    private func checkAnswers() {
        var allCorrect = true

        for person in personsToShow {
            let index = person.index
            let userAnswer = userAnswers[index].trimmingCharacters(in: .whitespacesAndNewlines)
            let correctForm = correctForms.first(where: { $0.personIndex == index })?.form ?? ""

            let isCorrect = userAnswer.compare(correctForm, options: .caseInsensitive, locale: Locale(identifier: "es")) == .orderedSame

            results[index] = isCorrect
            if !isCorrect { allCorrect = false }
        }

        isChecked = true
        sessionCount += 1
        if allCorrect { sessionCorrect += 1 }

        if let verb = currentVerb, let tense = currentTense {
            let service = PracticeSessionService(
                localContext: modelContext,
                cloudContext: cloudModelContext,
                reflexiveBaseInfinitives: ReflexiveVerbStore.shared.baseInfinitives
            )
            let reviewResults = Dictionary(uniqueKeysWithValues: personsToShow.map { ($0.index, results[$0.index] == true) })
            _ = service.recordFullTableReview(verbId: verb.id, tenseId: tense.id, results: reviewResults)
        }

        focusedField = nil
    }

    private func advanceFocus(from index: Int) {
        let remaining = personsToShow.filter { $0.index > index }
        if let next = remaining.first {
            focusedField = next.index
        } else {
            focusedField = nil
            if !isChecked { checkAnswers() }
        }
    }

    private func loadSettings() {
        let progress = ReviewStore.fetchOrCreateUserProgress(context: cloudModelContext)
        showVosotros = progress.showVosotros
        autoFillStem = progress.autoFillStem
    }

    private func foregroundColor(for index: Int) -> Color {
        guard let result = results[index] else { return .primary }
        return result ? .green : .red
    }

    private func dividerColor(for index: Int) -> Color {
        guard let result = results[index] else { return .secondary.opacity(0.3) }
        return result ? .green : .red
    }
}

#Preview {
    NavigationStack {
        FullTableView(speechService: SpeechService())
    }
    .modelContainer(for: [Verb.self, VerbForm.self, ReviewCard.self, UserProgress.self], inMemory: true)
}
