import SwiftUI
import SharedModels
import SwiftData

struct PracticeView: View {
    @Environment(\.modelContext) private var modelContext
    @Environment(\.cloudModelContextProvider) private var cloudModelContextProvider
    @State private var viewModel = PracticeViewModel()
    @State private var speechService = SpeechService()
    @State private var isPracticing = false
    @State private var userProgress: UserProgress?
    /// Cached due counts for the noun + adjective Review rows. Refreshed on
    /// appear, on session end (`isPracticing` change), and after the user
    /// returns from a Review screen. Avoids running `fetchCount` against the
    /// cloud context on every `body` re-evaluation.
    @State private var nounDueCount: Int = 0
    @State private var adjectiveDueCount: Int = 0

    private var cloudModelContext: ModelContext { cloudModelContextProvider() }

    var body: some View {
        NavigationStack {
            Group {
                if isPracticing {
                    practiceSessionView
                } else {
                    practiceHomeView
                }
            }
            // Book navigation is value-based and declared once here, at the
            // stack root. Eager `NavigationLink { destination }` forms inside
            // the List/LazyVStack of the book screens caused an infinite
            // render loop; value-based links build destinations lazily.
            .navigationDestination(for: BooksRoute.self) { _ in
                BookLibraryView()
            }
            .navigationDestination(for: Book.self) { book in
                BookChapterListView(book: book)
            }
            .navigationDestination(for: BookChapter.self) { chapter in
                BookReaderView(chapter: chapter)
            }
            .navigationTitle("Practice")
            .navigationBarTitleDisplayMode(.inline)
            .onAppear {
                loadProgress()
                refreshLexemeDueCounts()
            }
            .onChange(of: isPracticing) { _, practicing in
                if !practicing {
                    loadProgress()
                    refreshLexemeDueCounts()
                }
            }
            .toolbar {
                if isPracticing {
                    ToolbarItem(placement: .cancellationAction) {
                        Button("Done") {
                            withAnimation {
                                isPracticing = false
                            }
                        }
                    }

                    ToolbarItem(placement: .primaryAction) {
                        sessionStatsLabel
                    }
                }
            }
        }
    }

    // MARK: - Home View

    private var practiceHomeView: some View {
        ScrollView {
            VStack(spacing: 28) {
                // Daily progress
                if let progress = userProgress {
                    VStack(spacing: 8) {
                        DailyProgressRing(
                            current: progress.todayCount,
                            goal: progress.dailyGoal
                        )
                        .frame(width: 160, height: 160)

                        Text("\(progress.todayCount) / \(progress.dailyGoal)")
                            .font(.title3.weight(.semibold))
                            .foregroundStyle(.secondary)

                        if progress.currentStreak > 0 {
                            Label("\(progress.currentStreak) day streak", systemImage: "flame.fill")
                                .font(.subheadline.weight(.medium))
                                .foregroundStyle(.orange)
                        }
                    }
                    .padding(.top, 8)
                }

                // === Section: Conjugation ===
                sectionHeader("Conjugation")

                VStack(spacing: 12) {
                    ForEach(PracticeMode.allCases) { mode in
                        ModeButton(mode: mode) {
                            viewModel.practiceMode = mode
                            viewModel.focusMode = .none
                            viewModel.sessionCorrect = 0
                            viewModel.sessionTotal = 0
                            viewModel.loadNextCard(
                                localContext: modelContext,
                                cloudContext: cloudModelContext
                            )
                            withAnimation {
                                isPracticing = true
                            }
                        }
                    }
                }
                .padding(.horizontal)

                conjugationFocusButtons

                // === Section: Vocabulary ===
                sectionHeader("Vocabulary")
                vocabSection

                // === Section: Nouns ===
                sectionHeader("Nouns")
                nounsSection

                // === Section: Adjectives ===
                sectionHeader("Adjectives")
                adjectivesSection

                // === Section: Reading ===
                sectionHeader("Reading")

                // Lyrics
                NavigationLink {
                    LyricsLibraryView()
                } label: {
                    HStack(spacing: 14) {
                        Image(systemName: "music.note.list")
                            .font(.title3)
                            .frame(width: 36)
                            .foregroundStyle(.pink)

                        VStack(alignment: .leading, spacing: 2) {
                            Text("Lyrics")
                                .font(.subheadline.weight(.semibold))
                            Text("Read Spanish song lyrics with translations")
                                .font(.caption)
                                .foregroundStyle(.secondary)
                        }

                        Spacer()

                        Image(systemName: "chevron.right")
                            .font(.caption)
                            .foregroundStyle(.tertiary)
                    }
                    .padding(.horizontal, 16)
                    .padding(.vertical, 14)
                }
                .tint(.primary)
                .glassEffect(in: RoundedRectangle(cornerRadius: 14))
                .padding(.horizontal)

                // Conversation Practice
                NavigationLink {
                    ChatLibraryView()
                } label: {
                    HStack(spacing: 14) {
                        Image(systemName: "bubble.left.and.bubble.right.fill")
                            .font(.title3)
                            .frame(width: 36)
                            .foregroundStyle(.green)

                        VStack(alignment: .leading, spacing: 2) {
                            Text("Conversation")
                                .font(.subheadline.weight(.semibold))
                            Text("Chat with AI in Spanish scenarios")
                                .font(.caption)
                                .foregroundStyle(.secondary)
                        }

                        Spacer()

                        Image(systemName: "chevron.right")
                            .font(.caption)
                            .foregroundStyle(.tertiary)
                    }
                    .padding(.horizontal, 16)
                    .padding(.vertical, 14)
                }
                .tint(.primary)
                .glassEffect(in: RoundedRectangle(cornerRadius: 14))
                .padding(.horizontal)

                // Listening Practice
                NavigationLink {
                    ListeningView()
                } label: {
                    HStack(spacing: 14) {
                        Image(systemName: "ear.fill")
                            .font(.title3)
                            .frame(width: 36)
                            .foregroundStyle(.blue)

                        VStack(alignment: .leading, spacing: 2) {
                            Text("Listening")
                                .font(.subheadline.weight(.semibold))
                            Text("Listen and type, or practice pronunciation")
                                .font(.caption)
                                .foregroundStyle(.secondary)
                        }

                        Spacer()

                        Image(systemName: "chevron.right")
                            .font(.caption)
                            .foregroundStyle(.tertiary)
                    }
                    .padding(.horizontal, 16)
                    .padding(.vertical, 14)
                }
                .tint(.primary)
                .glassEffect(in: RoundedRectangle(cornerRadius: 14))
                .padding(.horizontal)

                // Cloze Practice
                NavigationLink {
                    ClozeView()
                } label: {
                    HStack(spacing: 14) {
                        Image(systemName: "text.badge.minus")
                            .font(.title3)
                            .frame(width: 36)
                            .foregroundStyle(.indigo)

                        VStack(alignment: .leading, spacing: 2) {
                            Text("Cloze Practice")
                                .font(.subheadline.weight(.semibold))
                            Text("Fill in the missing word in context")
                                .font(.caption)
                                .foregroundStyle(.secondary)
                        }

                        Spacer()

                        Image(systemName: "chevron.right")
                            .font(.caption)
                            .foregroundStyle(.tertiary)
                    }
                    .padding(.horizontal, 16)
                    .padding(.vertical, 14)
                }
                .tint(.primary)
                .glassEffect(in: RoundedRectangle(cornerRadius: 14))
                .padding(.horizontal)

                // Stories
                NavigationLink {
                    StoryLibraryView()
                } label: {
                    HStack(spacing: 14) {
                        Image(systemName: "book.fill")
                            .font(.title3)
                            .frame(width: 36)
                            .foregroundStyle(.teal)

                        VStack(alignment: .leading, spacing: 2) {
                            Text("Stories")
                                .font(.subheadline.weight(.semibold))
                            Text("Read AI-generated Spanish stories")
                                .font(.caption)
                                .foregroundStyle(.secondary)
                        }

                        Spacer()

                        Image(systemName: "chevron.right")
                            .font(.caption)
                            .foregroundStyle(.tertiary)
                    }
                    .padding(.horizontal, 16)
                    .padding(.vertical, 14)
                }
                .tint(.primary)
                .glassEffect(in: RoundedRectangle(cornerRadius: 14))
                .padding(.horizontal)

                // Books
                NavigationLink(value: BooksRoute.library) {
                    HStack(spacing: 14) {
                        Image(systemName: "books.vertical.fill")
                            .font(.title3)
                            .frame(width: 36)
                            .foregroundStyle(.indigo)

                        VStack(alignment: .leading, spacing: 2) {
                            Text("Books")
                                .font(.subheadline.weight(.semibold))
                            Text("Read full-length books with tap-to-define")
                                .font(.caption)
                                .foregroundStyle(.secondary)
                        }

                        Spacer()

                        Image(systemName: "chevron.right")
                            .font(.caption)
                            .foregroundStyle(.tertiary)
                    }
                    .padding(.horizontal, 16)
                    .padding(.vertical, 14)
                }
                .tint(.primary)
                .glassEffect(in: RoundedRectangle(cornerRadius: 14))
                .padding(.horizontal)

                // Session stats summary
                if viewModel.sessionTotal > 0 && !isPracticing {
                    VStack(spacing: 8) {
                        Text("Last Session")
                            .font(.headline)
                            .frame(maxWidth: .infinity, alignment: .leading)

                        HStack(spacing: 20) {
                            StatItem(label: "Reviewed", value: "\(viewModel.sessionTotal)")
                            StatItem(label: "Correct", value: "\(viewModel.sessionCorrect)")
                            StatItem(
                                label: "Accuracy",
                                value: "\(Int(viewModel.sessionAccuracy * 100))%"
                            )
                        }
                        .padding()
                        .frame(maxWidth: .infinity)
                        .glassEffect(in: RoundedRectangle(cornerRadius: 16))
                    }
                    .padding(.horizontal)
                }
            }
            .padding(.vertical)
            .adaptiveContainer()
        }
    }

    // MARK: - Section header

    private func sectionHeader(_ title: String) -> some View {
        Text(title)
            .font(.headline)
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding(.horizontal)
    }

    // MARK: - Conjugation focus buttons (Common Tenses / Weak Verbs / Irregularity)

    private var conjugationFocusButtons: some View {
        VStack(spacing: 12) {
            // Common Tenses
            Button {
                viewModel.practiceMode = .flashcard
                viewModel.focusMode = .commonTenses
                viewModel.sessionCorrect = 0
                viewModel.sessionTotal = 0
                viewModel.loadNextCard(localContext: modelContext, cloudContext: cloudModelContext)
                withAnimation { isPracticing = true }
            } label: {
                practiceRowLabel(icon: "star.fill", color: .orange,
                                 title: "Common Tenses",
                                 subtitle: "Practice the 6 most essential tenses")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            // Weak Verbs
            Button {
                viewModel.practiceMode = .flashcard
                viewModel.focusMode = .weakVerbs
                viewModel.sessionCorrect = 0
                viewModel.sessionTotal = 0
                viewModel.loadNextCard(localContext: modelContext, cloudContext: cloudModelContext)
                withAnimation { isPracticing = true }
            } label: {
                practiceRowLabel(icon: "exclamationmark.triangle", color: .red,
                                 title: "Weak Verbs",
                                 subtitle: "Focus on verbs you struggle with")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            // Irregularity drills
            Menu {
                Button("Spelling Changes (c→qu, z→c, ...)") { startIrregularityDrill(.spelling) }
                Button("Stem Changes (o→ue, e→ie, ...)") { startIrregularityDrill(.stemChange) }
                Button("Unique Irregulars (ser, ir, ...)") { startIrregularityDrill(.uniqueIrregular) }
            } label: {
                practiceRowLabel(icon: "wand.and.stars", color: .purple,
                                 title: "Irregularity Drills",
                                 subtitle: "Practice by irregularity type")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))
        }
        .padding(.horizontal)
    }

    // MARK: - Vocabulary section

    private var vocabSection: some View {
        VStack(spacing: 12) {
            // Vocab Flashcards (verb pool, filtered by Settings levels)
            NavigationLink {
                VocabFlashcardPracticeView()
            } label: {
                practiceRowLabel(icon: "rectangle.on.rectangle.angled", color: .purple,
                                 title: "Vocab Flashcards",
                                 subtitle: "Verb meaning → infinitive recall")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            // Vocab Multiple Choice (same verb pool)
            NavigationLink {
                VocabMultipleChoicePracticeView()
            } label: {
                practiceRowLabel(icon: "checklist", color: .purple,
                                 title: "Vocab Multiple Choice",
                                 subtitle: "Pick the Spanish infinitive from 4 options")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            // Review Learned — consolidation cram over already-studied verbs
            NavigationLink {
                VocabFlashcardPracticeView(kind: .reviewLearned)
            } label: {
                practiceRowLabel(icon: "clock.arrow.circlepath", color: .purple,
                                 title: "Review Learned — Flashcards",
                                 subtitle: "Re-review verbs you've studied — schedule unchanged")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            NavigationLink {
                VocabMultipleChoicePracticeView(kind: .reviewLearned)
            } label: {
                practiceRowLabel(icon: "clock.arrow.circlepath", color: .purple,
                                 title: "Review Learned — Multiple Choice",
                                 subtitle: "Multiple choice over verbs you've studied — schedule unchanged")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            // Existing: Vocab Review (due cards)
            NavigationLink {
                VocabReviewView()
            } label: {
                HStack(spacing: 14) {
                    Image(systemName: "rectangle.stack.fill")
                        .font(.title3)
                        .foregroundStyle(.teal)
                        .frame(width: 32)

                    VStack(alignment: .leading, spacing: 2) {
                        Text("Vocab Review")
                            .font(.subheadline.weight(.semibold))
                        Text("Review due vocabulary cards")
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }

                    Spacer()

                    let dueCount = VocabReviewView.dueCount(context: cloudModelContext)
                    if dueCount > 0 {
                        Text("\(dueCount)")
                            .font(.caption.weight(.bold))
                            .foregroundStyle(.white)
                            .padding(.horizontal, 8)
                            .padding(.vertical, 3)
                            .background(.teal, in: Capsule())
                    }

                    Image(systemName: "chevron.right")
                        .font(.caption)
                        .foregroundStyle(.tertiary)
                }
                .padding(.horizontal, 16)
                .padding(.vertical, 12)
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))
        }
        .padding(.horizontal)
    }

    // MARK: - Nouns section

    private var nounsSection: some View {
        VStack(spacing: 12) {
            NavigationLink {
                NounFlashcardPracticeView()
            } label: {
                practiceRowLabel(icon: "rectangle.on.rectangle.angled", color: .teal,
                                 title: "Noun Flashcards",
                                 subtitle: "English → Spanish noun (with article)")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            NavigationLink {
                NounMultipleChoicePracticeView()
            } label: {
                practiceRowLabel(icon: "checklist", color: .teal,
                                 title: "Noun Multiple Choice",
                                 subtitle: "Pick the Spanish noun from 4 options")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            NavigationLink {
                NounFlashcardPracticeView(kind: .reviewLearned)
            } label: {
                practiceRowLabel(icon: "clock.arrow.circlepath", color: .teal,
                                 title: "Review Learned — Flashcards",
                                 subtitle: "Re-review nouns you've studied — schedule unchanged")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            NavigationLink {
                NounMultipleChoicePracticeView(kind: .reviewLearned)
            } label: {
                practiceRowLabel(icon: "clock.arrow.circlepath", color: .teal,
                                 title: "Review Learned — Multiple Choice",
                                 subtitle: "Multiple choice over nouns you've studied — schedule unchanged")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            NavigationLink {
                NounReviewView()
            } label: {
                HStack(spacing: 14) {
                    Image(systemName: "rectangle.stack.fill")
                        .font(.title3)
                        .foregroundStyle(.teal)
                        .frame(width: 32)

                    VStack(alignment: .leading, spacing: 2) {
                        Text("Noun Review")
                            .font(.subheadline.weight(.semibold))
                        Text("Review due noun cards")
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }

                    Spacer()

                    if nounDueCount > 0 {
                        Text("\(nounDueCount)")
                            .font(.caption.weight(.bold))
                            .foregroundStyle(.white)
                            .padding(.horizontal, 8)
                            .padding(.vertical, 3)
                            .background(.teal, in: Capsule())
                    }

                    Image(systemName: "chevron.right")
                        .font(.caption)
                        .foregroundStyle(.tertiary)
                }
                .padding(.horizontal, 16)
                .padding(.vertical, 12)
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))
        }
        .padding(.horizontal)
    }

    // MARK: - Adjectives section

    private var adjectivesSection: some View {
        VStack(spacing: 12) {
            NavigationLink {
                AdjectiveFlashcardPracticeView()
            } label: {
                practiceRowLabel(icon: "rectangle.on.rectangle.angled", color: .pink,
                                 title: "Adjective Flashcards",
                                 subtitle: "English → Spanish adjective base form")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            NavigationLink {
                AdjectiveMultipleChoicePracticeView()
            } label: {
                practiceRowLabel(icon: "checklist", color: .pink,
                                 title: "Adjective Multiple Choice",
                                 subtitle: "Pick the Spanish adjective from 4 options")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            NavigationLink {
                AdjectiveFlashcardPracticeView(kind: .reviewLearned)
            } label: {
                practiceRowLabel(icon: "clock.arrow.circlepath", color: .pink,
                                 title: "Review Learned — Flashcards",
                                 subtitle: "Re-review adjectives you've studied — schedule unchanged")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            NavigationLink {
                AdjectiveMultipleChoicePracticeView(kind: .reviewLearned)
            } label: {
                practiceRowLabel(icon: "clock.arrow.circlepath", color: .pink,
                                 title: "Review Learned — Multiple Choice",
                                 subtitle: "Multiple choice over adjectives you've studied — schedule unchanged")
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))

            NavigationLink {
                AdjectiveReviewView()
            } label: {
                HStack(spacing: 14) {
                    Image(systemName: "rectangle.stack.fill")
                        .font(.title3)
                        .foregroundStyle(.pink)
                        .frame(width: 32)

                    VStack(alignment: .leading, spacing: 2) {
                        Text("Adjective Review")
                            .font(.subheadline.weight(.semibold))
                        Text("Review due adjective cards")
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }

                    Spacer()

                    if adjectiveDueCount > 0 {
                        Text("\(adjectiveDueCount)")
                            .font(.caption.weight(.bold))
                            .foregroundStyle(.white)
                            .padding(.horizontal, 8)
                            .padding(.vertical, 3)
                            .background(.pink, in: Capsule())
                    }

                    Image(systemName: "chevron.right")
                        .font(.caption)
                        .foregroundStyle(.tertiary)
                }
                .padding(.horizontal, 16)
                .padding(.vertical, 12)
            }
            .tint(.primary)
            .glassEffect(in: RoundedRectangle(cornerRadius: 14))
        }
        .padding(.horizontal)
    }

    private func practiceRowLabel(icon: String, color: Color, title: String, subtitle: String) -> some View {
        HStack(spacing: 14) {
            Image(systemName: icon)
                .font(.title3)
                .foregroundStyle(color)
                .frame(width: 32)

            VStack(alignment: .leading, spacing: 2) {
                Text(title)
                    .font(.subheadline.weight(.semibold))
                Text(subtitle)
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }

            Spacer()

            Image(systemName: "chevron.right")
                .font(.caption)
                .foregroundStyle(.tertiary)
        }
        .padding(.horizontal, 16)
        .padding(.vertical, 12)
    }

    // MARK: - Practice Session View

    @ViewBuilder
    private var practiceSessionView: some View {
        if !viewModel.hasCards {
            ContentUnavailableView(
                "No Cards Available",
                systemImage: "rectangle.on.rectangle.slash",
                description: Text("Add some verbs to your practice deck to get started.")
            )
        } else {
            switch viewModel.practiceMode {
            case .flashcard:
                FlashcardView(viewModel: viewModel, speechService: speechService)
            case .typing:
                TypingView(viewModel: viewModel, speechService: speechService)
            case .multipleChoice:
                MultipleChoiceView(viewModel: viewModel, speechService: speechService)
            case .fullTable:
                FullTableView(speechService: speechService)
            case .handwriting:
                HandwritingView(viewModel: viewModel, speechService: speechService)
            case .sentenceBuilder:
                SentenceBuilderView()
            }
        }
    }

    // MARK: - Session Stats Label

    private var sessionStatsLabel: some View {
        HStack(spacing: 4) {
            Image(systemName: "checkmark.circle.fill")
                .foregroundStyle(.green)
            Text("\(viewModel.sessionCorrect)/\(viewModel.sessionTotal)")
                .font(.subheadline.weight(.medium))
                .contentTransition(.numericText())
        }
    }
}

// MARK: - Mode Button

private struct ModeButton: View {
    let mode: PracticeMode
    let action: () -> Void

    private var description: String {
        switch mode {
        case .flashcard: "Reveal answers at your own pace"
        case .typing: "Type the conjugation from memory"
        case .multipleChoice: "Pick the correct form from options"
        case .fullTable: "Conjugate all persons for a verb + tense"
        case .handwriting: "Write the answer with Apple Pencil"
        case .sentenceBuilder: "Arrange Spanish words in correct order"
        }
    }

    var body: some View {
        Button(action: action) {
            HStack(spacing: 16) {
                Image(systemName: mode.icon)
                    .font(.title2)
                    .frame(width: 40)

                VStack(alignment: .leading, spacing: 2) {
                    Text(mode.label)
                        .font(.headline)

                    Text(description)
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }

                Spacer()

                Image(systemName: "chevron.right")
                    .font(.subheadline)
                    .foregroundStyle(.tertiary)
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 14)
        }
        .tint(.primary)
        .glassEffect(in: RoundedRectangle(cornerRadius: 16))
    }
}

// MARK: - Stat Item

private struct StatItem: View {
    let label: String
    let value: String

    var body: some View {
        VStack(spacing: 4) {
            Text(value)
                .font(.title2.bold().monospacedDigit())
                .contentTransition(.numericText())

            Text(label)
                .font(.caption)
                .foregroundStyle(.secondary)
        }
        .frame(maxWidth: .infinity)
    }
}

extension PracticeView {
    fileprivate func startIrregularityDrill(_ filter: IrregularityFilter) {
        viewModel.practiceMode = .flashcard
        viewModel.focusMode = .irregularity(filter)
        viewModel.sessionCorrect = 0
        viewModel.sessionTotal = 0
        viewModel.loadNextCard(localContext: modelContext, cloudContext: cloudModelContext)
        withAnimation { isPracticing = true }
    }

    private func refreshLexemeDueCounts() {
        nounDueCount = NounReviewView.dueCount(context: cloudModelContext)
        adjectiveDueCount = AdjectiveReviewView.dueCount(context: cloudModelContext)
    }

    private func loadProgress() {
        let progress = ReviewStore.fetchOrCreateUserProgress(context: cloudModelContext)
        userProgress = progress
        try? cloudModelContext.save()
    }
}

#Preview {
    PracticeView()
        .modelContainer(for: [UserProgress.self, ReviewCard.self, Verb.self], inMemory: true)
}
