import SwiftUI
import SharedModels
import SwiftData

/// English ↔ Spanish adjective flashcards. Same flow as the noun view and
/// the verb flashcards: show the English meaning, tap to reveal the Spanish
/// base form, rate Again/Hard/Good/Easy. Agreement (gender + number) is
/// taught organically through reading and verb-flashcard examples, not as a
/// separate quiz here.
///
/// Plain `ScrollView { VStack }` — no `LazyVStack`/`ScrollViewReader`.
struct AdjectiveFlashcardPracticeView: View {

    var kind: LexemeSessionKind = .standard

    @Environment(\.modelContext) private var localContext
    @Environment(\.cloudModelContextProvider) private var cloudModelContextProvider
    @Environment(\.dismiss) private var dismiss

    @State private var session: LexemeSessionQueue?
    @State private var revealed: Bool = false

    private var cloudContext: ModelContext { cloudModelContextProvider() }
    private var currentLexeme: Lexeme? { session?.current?.lexeme }

    private static let drillMode = "recall"

    var body: some View {
        ScrollView {
            VStack(spacing: 24) {
                headerBar
                if let lexeme = currentLexeme {
                    cardContent(for: lexeme)
                } else {
                    completionView
                }
            }
            .padding()
            .adaptiveContainer(maxWidth: 720)
        }
        .navigationTitle(kind == .reviewLearned ? "Review Learned" : "Adjectives")
        .navigationBarTitleDisplayMode(.inline)
        .onAppear(perform: loadIfNeeded)
        .animation(.smooth, value: revealed)
        .animation(.smooth, value: currentLexeme?.id)
    }

    // MARK: - Card

    @ViewBuilder
    private func cardContent(for lexeme: Lexeme) -> some View {
        Text(lexeme.english)
            .font(.largeTitle.weight(.bold))
            .multilineTextAlignment(.center)
            .padding(.top, 12)

        if revealed {
            VStack(spacing: 14) {
                Text(lexeme.baseForm)
                    .font(.title.weight(.semibold))
                    .multilineTextAlignment(.center)
                exampleBlock(for: lexeme)
                ratingButtons(for: lexeme)
            }
        } else {
            tapToReveal
        }
    }

    private var tapToReveal: some View {
        VStack(spacing: 8) {
            Image(systemName: "hand.tap").font(.title).foregroundStyle(.secondary)
            Text("Tap to reveal").font(.headline).foregroundStyle(.secondary)
        }
        .frame(maxWidth: .infinity, minHeight: 200)
        .glassEffect(in: RoundedRectangle(cornerRadius: 20))
        .contentShape(Rectangle())
        .onTapGesture {
            withAnimation(.smooth) { revealed = true }
        }
    }

    @ViewBuilder
    private func exampleBlock(for lexeme: Lexeme) -> some View {
        if let es = lexeme.exampleES, !es.isEmpty {
            VStack(alignment: .leading, spacing: 4) {
                Text(es).font(.subheadline).italic()
                if let en = lexeme.exampleEN, !en.isEmpty {
                    Text(en).font(.caption).foregroundStyle(.secondary)
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding()
            .background(.fill.quinary, in: RoundedRectangle(cornerRadius: 12))
        }
    }

    // MARK: - Header

    @ViewBuilder
    private var headerBar: some View {
        VStack(spacing: 6) {
            ProgressView(value: session?.progress ?? 0).tint(.pink)
            Text(progressLabel)
                .font(.caption)
                .foregroundStyle(.secondary)
        }
    }

    private var progressLabel: String {
        guard let session else { return "Loading…" }
        if session.isComplete { return "Done" }
        return "\(session.learnedCount) learned · \(session.remainingCount) to go"
    }

    // MARK: - Rating

    private func ratingButtons(for lexeme: Lexeme) -> some View {
        VStack(spacing: 10) {
            Text("How well did you know it?")
                .font(.subheadline)
                .foregroundStyle(.secondary)
            HStack(spacing: 10) {
                ratingButton("Again", color: .red, rating: .again, lexeme: lexeme)
                ratingButton("Hard", color: .orange, rating: .hard, lexeme: lexeme)
                ratingButton("Good", color: .green, rating: .good, lexeme: lexeme)
                ratingButton("Easy", color: .blue, rating: .easy, lexeme: lexeme)
            }
        }
    }

    private func ratingButton(_ label: String, color: Color, rating: LexemeSessionQueue.Rating, lexeme: Lexeme) -> some View {
        Button {
            answer(rating, for: lexeme)
        } label: {
            Text(label)
                .font(.subheadline.weight(.semibold))
                .frame(maxWidth: .infinity)
                .padding(.vertical, 12)
        }
        .tint(color)
        .glassEffect(in: RoundedRectangle(cornerRadius: 12))
    }

    private func answer(_ rating: LexemeSessionQueue.Rating, for lexeme: Lexeme) {
        let graduation = session?.answer(rating)
        if let graduation, kind == .standard {
            LexemeReviewStore(context: cloudContext).rate(
                lexemeId: lexeme.id,
                partOfSpeech: "adjective",
                drillMode: Self.drillMode,
                quality: graduation
            )
        }
        persistGroup()
        withAnimation(.smooth) { revealed = false }
    }

    // MARK: - Completion

    private var completionView: some View {
        VStack(spacing: 16) {
            Image(systemName: "checkmark.circle.fill")
                .font(.system(size: 56)).foregroundStyle(.green)
            Text(completionTitle).font(.title2.bold())
            Text(completionDetail)
                .font(.subheadline)
                .foregroundStyle(.secondary)
                .multilineTextAlignment(.center)

            HStack(spacing: 12) {
                Button { studyAgain() } label: {
                    Label("Next Set", systemImage: "arrow.right")
                        .font(.subheadline.weight(.semibold))
                        .padding(.vertical, 6)
                        .frame(maxWidth: .infinity)
                }
                .buttonStyle(.borderedProminent)
                .tint(.pink)

                Button("Done") { dismiss() }
                    .font(.subheadline.weight(.semibold))
                    .padding(.vertical, 6)
                    .frame(maxWidth: .infinity)
                    .buttonStyle(.bordered)
            }
            .padding(.top, 12)
        }
        .padding(.top, 60)
        .padding(.horizontal, 24)
    }

    private var completionTitle: String {
        let learned = session?.learnedCount ?? 0
        return learned > 0 ? "Session Complete" : "Nothing Available"
    }

    private var completionDetail: String {
        let learned = session?.learnedCount ?? 0
        if learned > 0 {
            return "\(learned) adjective\(learned == 1 ? "" : "s") learned"
        }
        let progress = ReviewStore.fetchOrCreateUserProgress(context: cloudContext)
        if progress.selectedLexemeLevels.isEmpty {
            return "No vocabulary levels enabled. Open Settings → Vocabulary Levels to turn some on."
        }
        return "No adjectives available at the enabled levels right now."
    }

    // MARK: - Session lifecycle

    private func loadIfNeeded() {
        guard session == nil else { return }
        switch kind {
        case .reviewLearned:
            let lexemes = LexemePool.reviewLearnedLexemes(
                partOfSpeech: "adjective",
                drillMode: Self.drillMode,
                localContext: localContext,
                cloudContext: cloudContext
            )
            session = LexemeSessionQueue(lexemes: lexemes, drillMode: Self.drillMode)
            return

        case .standard:
            let store = LexemeStudyGroupStore(
                context: cloudContext,
                partOfSpeech: "adjective",
                drillMode: Self.drillMode
            )
            if let group = store.activeGroup() {
                let stored = group.entries
                if !stored.isEmpty {
                    let byId = lexemesByID(Set(stored.map(\.lexemeId)))
                    let entries: [(lexeme: Lexeme, state: LexemeSessionQueue.CardState)] = stored.compactMap { e in
                        guard let lex = byId[e.lexemeId] else { return nil }
                        return (lex, LexemeSessionQueue.CardState(rawValue: e.state) ?? .new)
                    }
                    if entries.count == stored.count {
                        session = LexemeSessionQueue(
                            entries: entries,
                            drillMode: Self.drillMode,
                            learnedCount: group.learnedCount
                        )
                        return
                    }
                }
            }
            let progress = ReviewStore.fetchOrCreateUserProgress(context: cloudContext)
            let lexemes = LexemePool.sessionLexemes(
                partOfSpeech: "adjective",
                drillMode: Self.drillMode,
                enabledLevels: progress.selectedLexemeLevels,
                localContext: localContext,
                cloudContext: cloudContext
            )
            session = LexemeSessionQueue(lexemes: lexemes, drillMode: Self.drillMode)
            persistGroup()
        }
    }

    private func lexemesByID(_ ids: Set<String>) -> [String: Lexeme] {
        let descriptor = FetchDescriptor<Lexeme>(
            predicate: #Predicate<Lexeme> { ids.contains($0.id) }
        )
        let all = (try? localContext.fetch(descriptor)) ?? []
        return Dictionary(all.map { ($0.id, $0) }, uniquingKeysWith: { existing, _ in existing })
    }

    private func persistGroup() {
        guard kind == .standard, let session else { return }
        let store = LexemeStudyGroupStore(
            context: cloudContext,
            partOfSpeech: "adjective",
            drillMode: Self.drillMode
        )
        if session.isComplete {
            store.clear()
        } else {
            let entries = session.snapshot().map {
                StoredLexemeEntry(lexemeId: $0.lexemeId, state: $0.state.rawValue)
            }
            store.persist(entries: entries, learnedCount: session.learnedCount)
        }
    }

    private func studyAgain() {
        switch kind {
        case .reviewLearned:
            session?.restart()
        case .standard:
            LexemeStudyGroupStore(
                context: cloudContext,
                partOfSpeech: "adjective",
                drillMode: Self.drillMode
            ).clear()
            let progress = ReviewStore.fetchOrCreateUserProgress(context: cloudContext)
            let lexemes = LexemePool.sessionLexemes(
                partOfSpeech: "adjective",
                drillMode: Self.drillMode,
                enabledLevels: progress.selectedLexemeLevels,
                localContext: localContext,
                cloudContext: cloudContext
            )
            session = LexemeSessionQueue(lexemes: lexemes, drillMode: Self.drillMode)
            persistGroup()
        }
        revealed = false
    }
}
