import SwiftUI
import SwiftData

struct HomeView: View {
    @Environment(\.horizontalSizeClass) private var horizontalSizeClass
    @Environment(\.modelContext) private var context
    @Environment(\.openURL) private var openURL
    @Query private var dishes: [Dish]
    @Query private var tags: [Tag]
    @Query(sort: \WeekPlan.weekStartDate, order: .forward) private var weekPlans: [WeekPlan]
    @Query private var allSettings: [AppSettings]
    @StateObject private var viewModel = HomeViewModel()
    @State private var editingDish: Dish?
    @State private var showPremiumFromExport: Bool = false
    @State private var showMonthlyHistory: Bool = false
    @State private var showWeekLimitUpsell: Bool = false
    @State private var wasWeekComplete: Bool = false
    @State private var selectedEmptySlotId: UUID?
    @State private var showWeekPicker: Bool = false
    @State private var weekPickerDate: Date = Date()
    @State private var showCopyPreviousConfirm: Bool = false
    @State private var showReviewSentimentPrompt: Bool = false
    @State private var showReviewSupportPrompt: Bool = false
    @State private var showPostOnboardingAutoAssignPrompt: Bool = false
    @State private var showPostOnboardingPremiumPrompt: Bool = false
    @State private var hasEvaluatedPostOnboardingPrompts: Bool = false

    private var settings: AppSettings? { allSettings.first }

    var body: some View {
        NavigationStack {
            ZStack {
                Color.mealMoodBackground.ignoresSafeArea()

                if let settings = settings {
                    let plan = viewModel.getOrCreateWeekPlan(context: context, settings: settings)
                    if let plan {
                        mainContent(plan: plan, settings: settings)
                    }
                }
            }
            .toast(isShowing: $viewModel.showToast, message: viewModel.toastMessage)
            .navigationTitle("")
            .navigationBarTitleDisplayMode(.inline)
            .toolbarBackground(Color.mealMoodCoral.opacity(0.22), for: .navigationBar)
            .toolbarBackground(.visible, for: .navigationBar)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    HStack(spacing: 12) {
                        NavigationLink(destination: SettingsView()) {
                            Image(systemName: "gearshape")
                                .foregroundColor(.mealMoodTextPrimary)
                        }

                        if settings?.isPremium == true {
                            Button {
                                showMonthlyHistory = true
                            } label: {
                                Image(systemName: "calendar")
                                    .foregroundColor(.mealMoodTextPrimary)
                            }
                        }
                    }
                }
                ToolbarItem(placement: .principal) {
                    HStack(spacing: 10) {
                        if let settings = settings {
                            Button {
                                viewModel.goToPreviousWeek()
                                showWeekLimitUpsell = false
                            } label: {
                                Image(systemName: "chevron.left")
                                    .foregroundColor(.mealMoodCoral)
                            }
                            .accessibilityLabel(Text("home_previous"))

                            Button {
                                weekPickerDate = viewModel.currentWeekStart
                                showWeekPicker = true
                            } label: {
                                VStack(spacing: 2) {
                                    Text(viewModel.weekRangeText)
                                        .font(.mealMoodH2)
                                        .foregroundColor(.mealMoodTextPrimary)
                                }
                            }
                            .buttonStyle(.plain)
                            .accessibilityLabel(Text("home_select_week"))

                            Button {
                                if canNavigateToNextWeek(settings: settings) {
                                    viewModel.goToNextWeek()
                                    showWeekLimitUpsell = false
                                } else {
                                    withAnimation(.easeInOut(duration: 0.2)) {
                                        showWeekLimitUpsell = true
                                    }
                                    showPremiumFromExport = true
                                    HapticManager.shared.notification(type: .warning)
                                }
                            } label: {
                                Image(systemName: "chevron.right")
                                    .foregroundColor(.mealMoodCoral)
                            }
                            .accessibilityLabel(Text("home_next"))
                        }
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    HStack(spacing: 10) {
                        if let settings = settings,
                           let plan = viewModel.getOrCreateWeekPlan(context: context, settings: settings) {
                            if viewModel.canEditCurrentWeek {
                                Button {
                                    viewModel.autoComplete(plan: plan, dishes: dishes, tags: tags, settings: settings)
                                } label: {
                                    Image(systemName: "wand.and.stars")
                                        .foregroundColor(.mealMoodTextPrimary)
                                }
                                .contextMenu {
                                    Button {
                                        viewModel.undoLastAction(plan: plan, settings: settings)
                                    } label: {
                                        Label("home_undo_last_action", systemImage: "arrow.uturn.backward")
                                    }
                                    .disabled(!viewModel.canUndo(for: plan))

                                    Button {
                                        if plan.slots.contains(where: { $0.dishId != nil }) {
                                            showCopyPreviousConfirm = true
                                        } else {
                                            copyFromPreviousWeek(currentPlan: plan, settings: settings)
                                        }
                                    } label: {
                                        Label("home_copy_previous_week", systemImage: "doc.on.doc")
                                    }

                                    Button(role: .destructive) {
                                        viewModel.showResetAlert = true
                                    } label: {
                                        Label("home_reset", systemImage: "arrow.counterclockwise")
                                    }
                                }
                                .accessibilityLabel(Text("home_complete"))
                                .disabled(viewModel.isAutoCompleting || dishes.isEmpty)

                                if settings.syncEnabled && settings.syncModeEnum == .manual {
                                    Button {
                                        viewModel.syncWeekToCalendar(plan: plan, dishes: dishes, settings: settings)
                                    } label: {
                                        Image(systemName: "arrow.triangle.2.circlepath")
                                            .foregroundColor(.mealMoodTextPrimary)
                                    }
                                    .accessibilityLabel(Text("settings_sync_now"))
                                }
                            }
                        }
                    }
                }
            }
        }
        .onAppear {
            guard let settings = settings,
                  let plan = viewModel.getOrCreateWeekPlan(context: context, settings: settings) else { return }
            viewModel.reconcileSlotsIfNeeded(plan: plan, settings: settings, context: context)
        }
        .onChange(of: settings?.includeWeekends) { _, _ in
            guard let settings = settings,
                  let plan = viewModel.getOrCreateWeekPlan(context: context, settings: settings) else { return }
            viewModel.reconcileSlotsIfNeeded(plan: plan, settings: settings, context: context)
        }
        .onChange(of: settings?.mealWindows) { _, _ in
            guard let settings = settings,
                  let plan = viewModel.getOrCreateWeekPlan(context: context, settings: settings) else { return }
            viewModel.reconcileSlotsIfNeeded(plan: plan, settings: settings, context: context)
        }
        .onChange(of: viewModel.currentWeekStart) { _, _ in
            guard let settings = settings,
                  let plan = viewModel.getOrCreateWeekPlan(context: context, settings: settings) else { return }
            viewModel.reconcileSlotsIfNeeded(plan: plan, settings: settings, context: context)
        }
    }

    @ViewBuilder
    private func mainContent(plan: WeekPlan, settings: AppSettings) -> some View {
        VStack(spacing: 0) {
            if showWeekLimitUpsell && !settings.isPremium {
                PremiumUpsellBanner(
                    messageKey: "premium_limit_future_weeks",
                    actionTitleKey: "premium_subscribe"
                ) {
                    showPremiumFromExport = true
                }
                .padding(.horizontal, 16)
                .padding(.bottom, 8)
            }

            VStack(spacing: 10) {
                WeekCalendarView(
                    plan: plan,
                    settings: settings,
                    dishes: dishes,
                    tags: tags,
                    viewModel: viewModel,
                    onTapEmptySlot: { slot in
                        selectedEmptySlotId = slot.id
                    }
                )

                if isWeekComplete(plan: plan) {
                    exportCallout(plan: plan, settings: settings)
                }

                ScrollView(showsIndicators: true) {
                    dishDrawer(plan: plan, settings: settings)
                        .padding(.bottom, 0)
                }
                .frame(maxHeight: .infinity)
            }
            .frame(maxWidth: horizontalSizeClass == .regular ? 1160 : .infinity)
            .frame(maxWidth: .infinity, alignment: .top)
            .padding(.horizontal, horizontalSizeClass == .regular ? 14 : 0)
            .padding(.bottom, 0)
        }
        .frame(maxHeight: .infinity, alignment: .top)
        .safeAreaInset(edge: .bottom, spacing: 0) {
            if !settings.isPremium {
                AdBannerView()
            }
        }
        .alert("reset_title", isPresented: $viewModel.showResetAlert) {
            Button(String(localized: "reset_cancel"), role: .cancel) {}
            Button(String(localized: "reset_confirm"), role: .destructive) {
                viewModel.resetWeek(plan: plan, settings: settings)
            }
        } message: {
            Text("reset_message")
        }
        .alert("copy_previous_confirm_title", isPresented: $showCopyPreviousConfirm) {
            Button("reset_cancel", role: .cancel) {}
            Button("copy_previous_confirm_confirm", role: .destructive) {
                copyFromPreviousWeek(currentPlan: plan, settings: settings)
            }
        } message: {
            Text("copy_previous_confirm_message")
        }
        .alert(item: $viewModel.invalidDropContext) { context in
            Alert(
                title: Text("rule_override_title"),
                message: Text("rule_override_message"),
                primaryButton: .destructive(Text("rule_override_confirm")) {
                    viewModel.assignDish(context.dish, to: context.slot, plan: plan, settings: settings, isOverride: true)
                },
                secondaryButton: .cancel(Text("reset_cancel"))
            )
        }
        .alert("onboarding_auto_assign_title", isPresented: $showPostOnboardingAutoAssignPrompt) {
            Button("onboarding_auto_assign_yes") {
                viewModel.autoComplete(plan: plan, dishes: dishes, tags: tags, settings: settings)
                UserDefaults.standard.set(false, forKey: OnboardingViewModel.pendingAutoAssignPromptKey)
                schedulePostOnboardingPremiumPromptIfNeeded(settings: settings)
            }
            Button("onboarding_auto_assign_no", role: .cancel) {
                UserDefaults.standard.set(false, forKey: OnboardingViewModel.pendingAutoAssignPromptKey)
                schedulePostOnboardingPremiumPromptIfNeeded(settings: settings)
            }
        } message: {
            Text("onboarding_auto_assign_message")
        }
        .alert("onboarding_premium_prompt_title", isPresented: $showPostOnboardingPremiumPrompt) {
            Button("onboarding_premium_prompt_cta") {
                UserDefaults.standard.set(false, forKey: OnboardingViewModel.pendingPremiumPromptKey)
                showPremiumFromExport = true
            }
            Button("reset_cancel", role: .cancel) {
                UserDefaults.standard.set(false, forKey: OnboardingViewModel.pendingPremiumPromptKey)
            }
        } message: {
            Text("onboarding_premium_prompt_message")
        }
        .alert("review_funnel_title", isPresented: $showReviewSentimentPrompt) {
            Button("review_funnel_positive") {
                ReviewPromptService.shared.requestReview()
                ReviewPromptService.shared.markReviewCompleted()
            }
            Button("review_funnel_negative", role: .destructive) {
                showReviewSupportPrompt = true
            }
            Button("reset_cancel", role: .cancel) {}
        } message: {
            Text("review_funnel_message")
        }
        .alert("review_feedback_title", isPresented: $showReviewSupportPrompt) {
            Button("review_feedback_contact") {
                if let url = URL(string: "mailto:support@mealmood.app?subject=MealMood%20Feedback") {
                    openURL(url)
                }
            }
            Button("reset_cancel", role: .cancel) {}
        } message: {
            Text("review_feedback_message")
        }
        .sheet(isPresented: $viewModel.showDishForm) {
            DishFormView()
        }
        .sheet(isPresented: $showWeekPicker) {
            NavigationStack {
                Form {
                    DatePicker(
                        "home_week_picker_date",
                        selection: $weekPickerDate,
                        displayedComponents: .date
                    )
                    .datePickerStyle(.graphical)
                }
                .scrollContentBackground(.hidden)
                .background(Color.mealMoodBackground)
                .navigationTitle("home_week_picker_title")
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .cancellationAction) {
                        Button("reset_cancel") {
                            showWeekPicker = false
                        }
                    }
                    ToolbarItem(placement: .confirmationAction) {
                        Button("home_week_picker_go") {
                            jumpToSelectedWeek()
                            showWeekPicker = false
                        }
                    }
                }
            }
            .presentationDetents([.medium, .large])
        }
        .sheet(
            isPresented: Binding(
                get: { selectedEmptySlotId != nil },
                set: { isPresented in
                    if !isPresented { selectedEmptySlotId = nil }
                }
            )
        ) {
            if let slotId = selectedEmptySlotId,
               plan.slots.contains(where: { $0.id == slotId }) {
                SlotDishPickerSheet(
                    dishes: dishes,
                    tags: tags,
                    onPickDish: { dish in
                        guard let freshSlot = plan.slots.first(where: { $0.id == slotId }) else {
                            selectedEmptySlotId = nil
                            return
                        }
                        let isValid = AutocompleteEngine.validateDrop(
                            dish: dish,
                            slot: freshSlot,
                            plan: plan,
                            allTags: tags,
                            allDishes: dishes
                        )
                        if isValid {
                            viewModel.assignDish(dish, to: freshSlot, plan: plan, settings: settings)
                        } else {
                            // In picker flow, assign anyway and mark as override so the action is never lost.
                            viewModel.assignDish(dish, to: freshSlot, plan: plan, settings: settings, isOverride: true)
                        }
                        selectedEmptySlotId = nil
                    },
                    onCreateDish: {
                        selectedEmptySlotId = nil
                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
                            viewModel.showDishForm = true
                        }
                    }
                )
            }
        }
        .sheet(item: $editingDish) { dish in
            DishFormView(dish: dish)
        }
        .sheet(isPresented: $showPremiumFromExport) {
            NavigationStack {
                PremiumView(settings: settings)
            }
        }
        .sheet(isPresented: $showMonthlyHistory) {
            MonthlyHistoryView(
                weekPlans: weekPlans,
                currentWeekStart: viewModel.currentWeekStart,
                language: settings.languageEnum.resolved()
            ) { weekStart in
                viewModel.jumpToWeek(startDate: weekStart)
                showMonthlyHistory = false
            }
        }
        .task {
            await NotificationService.shared.requestPermissionIfNeeded()
            let nextPlan = fetchWeekPlan(for: Date().startOfWeek().addingDays(7))
            NotificationService.shared.schedulePlanningReminderIfNeeded(
                nextWeekPlan: nextPlan,
                language: settings.languageEnum.resolved()
            )
            wasWeekComplete = isWeekComplete(plan: plan)
            evaluatePostOnboardingPromptsIfNeeded(plan: plan, settings: settings)
        }
        .onChange(of: plan.updatedAt) { _, _ in
            let nowComplete = isWeekComplete(plan: plan)
            if nowComplete && !wasWeekComplete {
                evaluateReviewPrompt()
            }
            wasWeekComplete = nowComplete
        }
    }

    private struct SlotDishPickerSheet: View {
        let dishes: [Dish]
        let tags: [Tag]
        let onPickDish: (Dish) -> Void
        let onCreateDish: () -> Void

        @Environment(\.dismiss) private var dismiss
        @State private var searchText: String = ""

        private var filteredDishes: [Dish] {
            let trimmed = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
            guard !trimmed.isEmpty else {
                return dishes.sorted { $0.name.localizedCaseInsensitiveCompare($1.name) == .orderedAscending }
            }
            return dishes
                .filter { $0.name.localizedCaseInsensitiveContains(trimmed) }
                .sorted { $0.name.localizedCaseInsensitiveCompare($1.name) == .orderedAscending }
        }

        var body: some View {
            NavigationStack {
                Group {
                    if dishes.isEmpty {
                        VStack(spacing: 16) {
                            Text("home_pick_dish_no_dishes")
                                .font(.mealMoodBody)
                                .foregroundColor(.mealMoodTextSecondary)
                            Button {
                                dismiss()
                                onCreateDish()
                            } label: {
                                Label("home_pick_dish_add_new", systemImage: "plus")
                                    .font(.mealMoodBodyBold)
                                    .foregroundColor(.mealMoodCoral)
                            }
                        }
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .padding(24)
                    } else {
                        List {
                            ForEach(filteredDishes) { dish in
                                Button {
                                    onPickDish(dish)
                                    dismiss()
                                } label: {
                                    VStack(alignment: .leading, spacing: 6) {
                                        Text(dish.name)
                                            .font(.mealMoodBodyBold)
                                            .foregroundColor(.mealMoodTextPrimary)
                                        HStack(spacing: 4) {
                                            let dishTags = tags.filter { dish.tagIds.contains($0.id) }
                                            ForEach(dishTags.prefix(3), id: \.id) { tag in
                                                TagDot(color: tag.color, size: 8)
                                            }
                                        }
                                    }
                                    .padding(.vertical, 2)
                                }
                                .listRowBackground(Color.mealMoodSurface)
                            }

                            if filteredDishes.isEmpty {
                                Text("home_pick_dish_empty")
                                    .font(.mealMoodBody)
                                    .foregroundColor(.mealMoodTextSecondary)
                                    .listRowBackground(Color.mealMoodSurface)
                            }
                        }
                        .listStyle(.plain)
                        .scrollContentBackground(.hidden)
                        .background(Color.mealMoodBackground)
                        .searchable(text: $searchText, prompt: Text("home_pick_dish_search"))
                    }
                }
                .background(Color.mealMoodBackground.ignoresSafeArea())
                .environment(\.colorScheme, .light)
                .navigationTitle("home_pick_dish_title")
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .navigationBarLeading) {
                        Button("dish_cancel") { dismiss() }
                    }
                    ToolbarItem(placement: .navigationBarTrailing) {
                        Button {
                            dismiss()
                            onCreateDish()
                        } label: {
                            Image(systemName: "plus")
                        }
                        .accessibilityLabel(Text("home_pick_dish_add_new"))
                    }
                }
            }
        }
    }

    private func dishDrawer(plan: WeekPlan, settings: AppSettings) -> some View {
        DishDrawerView(
            dishes: dishes,
            tags: tags,
            language: settings.languageEnum.resolved(),
            usedDishIds: Set(plan.slots.compactMap(\.dishId)),
            onAddDish: { viewModel.showDishForm = true },
            onQuickAssignDish: { dish in
                viewModel.assignDishToFirstFreeSlot(
                    dish,
                    plan: plan,
                    settings: settings,
                    allTags: tags,
                    allDishes: dishes
                )
            },
            onEditDish: { dish in
                editingDish = dish
            },
            onDeleteDish: { dish in
                let isAssignedInCurrentWeek = plan.slots.contains { $0.dishId == dish.id }
                if isAssignedInCurrentWeek {
                    viewModel.toastMessage = localizedString("dish_delete_blocked_message", language: settings.languageEnum.resolved())
                    viewModel.showToast = true
                    return
                }
                context.delete(dish)
                try? context.save()
                viewModel.toastMessage = localizedString("toast_dish_deleted", language: settings.languageEnum.resolved())
                viewModel.showToast = true
            },
            draggedDish: $viewModel.draggedDish
        )
    }

    private func canNavigateToNextWeek(settings: AppSettings) -> Bool {
        if settings.isPremium { return true }
        let maxFreeWeek = Date().startOfWeek().addingDays(7)
        return viewModel.currentWeekStart < maxFreeWeek
    }

    private func canNavigateToWeek(_ startDate: Date, settings: AppSettings) -> Bool {
        if settings.isPremium { return true }
        let maxFreeWeek = Date().startOfWeek().addingDays(7)
        return startDate <= maxFreeWeek
    }

    private func jumpToSelectedWeek() {
        guard let settings else { return }
        let selectedWeekStart = weekPickerDate.startOfWeek()
        if canNavigateToWeek(selectedWeekStart, settings: settings) {
            viewModel.jumpToWeek(startDate: selectedWeekStart)
            showWeekLimitUpsell = false
        } else {
            withAnimation(.easeInOut(duration: 0.2)) {
                showWeekLimitUpsell = true
            }
            showPremiumFromExport = true
            HapticManager.shared.notification(type: .warning)
        }
    }

    private func isWeekComplete(plan: WeekPlan) -> Bool {
        plan.slots.allSatisfy { $0.dishId != nil }
    }

    @ViewBuilder
    private func exportCallout(plan: WeekPlan, settings: AppSettings) -> some View {
        VStack(alignment: .leading, spacing: 10) {
            Text("share_week_callout_title")
                .font(.mealMoodBodyBold)
                .foregroundColor(.mealMoodTextPrimary)
            Text("share_week_callout_subtitle")
                .font(.mealMoodCaption)
                .foregroundColor(.mealMoodTextSecondary)

            if settings.isPremium,
               let image = renderWeekShareImage(plan: plan, settings: settings),
               let shareURL = persistShareImage(image) {
                ShareLink(
                    item: shareURL,
                    preview: SharePreview(String(localized: "share_week_title"), image: Image(uiImage: image))
                ) {
                    Label("share_week_button", systemImage: "square.and.arrow.up")
                        .font(.mealMoodBodyBold)
                        .foregroundColor(.mealMoodTextPrimary)
                        .frame(maxWidth: .infinity)
                        .padding(.vertical, 10)
                        .background(Color.white.opacity(0.75))
                        .clipShape(RoundedRectangle(cornerRadius: 10))
                }
            } else {
                Button {
                    showPremiumFromExport = true
                } label: {
                    Label("share_week_button", systemImage: "star.fill")
                        .font(.mealMoodBodyBold)
                        .foregroundColor(.mealMoodTextPrimary)
                        .frame(maxWidth: .infinity)
                        .padding(.vertical, 10)
                        .background(Color.white.opacity(0.75))
                        .clipShape(RoundedRectangle(cornerRadius: 10))
                }
                .buttonStyle(.plain)
            }
        }
        .padding(12)
        .background(
            RoundedRectangle(cornerRadius: 12)
                .fill(Color.mealMoodMint.opacity(0.55))
        )
        .overlay(
            RoundedRectangle(cornerRadius: 12)
                .stroke(Color.mealMoodCoral.opacity(0.4), lineWidth: 1)
        )
        .padding(.horizontal, 16)
    }

    private func copyFromPreviousWeek(currentPlan: WeekPlan, settings: AppSettings) {
        let previousPlan = fetchWeekPlan(for: viewModel.currentWeekStart.addingDays(-7))
        viewModel.copyFromPreviousWeek(
            currentPlan: currentPlan,
            previousPlan: previousPlan,
            settings: settings,
            allTags: tags,
            allDishes: dishes
        )
    }

    private func renderWeekShareImage(plan: WeekPlan, settings: AppSettings) -> UIImage? {
        let renderer = ImageRenderer(content: WeekPlanShareView(plan: plan, settings: settings, dishes: dishes, tags: tags))
        renderer.proposedSize = ProposedViewSize(
            width: WeekPlanShareView.a4LandscapeWidth,
            height: WeekPlanShareView.a4LandscapeHeight
        )
        renderer.scale = 1
        return renderer.uiImage
    }

    private func persistShareImage(_ image: UIImage) -> URL? {
        guard let data = image.pngData() else { return nil }
        let url = FileManager.default.temporaryDirectory.appendingPathComponent("mealmood-week-plan.png")
        try? data.write(to: url, options: .atomic)
        return url
    }

    private func fetchWeekPlan(for weekStartDate: Date) -> WeekPlan? {
        let descriptor = FetchDescriptor<WeekPlan>(
            predicate: #Predicate<WeekPlan> { plan in
                plan.weekStartDate == weekStartDate
            }
        )
        return try? context.fetch(descriptor).first
    }

    private func evaluateReviewPrompt() {
        let descriptor = FetchDescriptor<WeekPlan>()
        guard let plans = try? context.fetch(descriptor) else { return }
        let completedWeeks = plans.filter { !$0.slots.isEmpty && $0.slots.allSatisfy { $0.dishId != nil } }.count
        guard ReviewPromptService.shared.shouldShowFunnelAfterWeekCompletion(completedWeeks: completedWeeks) else { return }
        ReviewPromptService.shared.markFunnelShown(completedWeeks: completedWeeks)
        showReviewSentimentPrompt = true
    }

    private func evaluatePostOnboardingPromptsIfNeeded(plan: WeekPlan, settings: AppSettings) {
        guard !hasEvaluatedPostOnboardingPrompts else { return }
        hasEvaluatedPostOnboardingPrompts = true

        let shouldAskAutoAssign = UserDefaults.standard.bool(forKey: OnboardingViewModel.pendingAutoAssignPromptKey)
        if shouldAskAutoAssign && plan.slots.contains(where: { $0.dishId == nil }) {
            showPostOnboardingAutoAssignPrompt = true
            return
        }

        UserDefaults.standard.set(false, forKey: OnboardingViewModel.pendingAutoAssignPromptKey)
        schedulePostOnboardingPremiumPromptIfNeeded(settings: settings)
    }

    private func schedulePostOnboardingPremiumPromptIfNeeded(settings: AppSettings) {
        guard !settings.isPremium else {
            UserDefaults.standard.set(false, forKey: OnboardingViewModel.pendingPremiumPromptKey)
            return
        }

        let shouldShowPremiumPrompt = UserDefaults.standard.bool(forKey: OnboardingViewModel.pendingPremiumPromptKey)
        guard shouldShowPremiumPrompt else { return }

        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            showPostOnboardingPremiumPrompt = true
        }
    }
}

private struct MonthlyHistoryView: View {
    let weekPlans: [WeekPlan]
    let currentWeekStart: Date
    let language: AppLanguage
    let onSelectWeek: (Date) -> Void

    @Environment(\.dismiss) private var dismiss
    @State private var monthCursor: Date

    init(
        weekPlans: [WeekPlan],
        currentWeekStart: Date,
        language: AppLanguage,
        onSelectWeek: @escaping (Date) -> Void
    ) {
        self.weekPlans = weekPlans
        self.currentWeekStart = currentWeekStart
        self.language = language
        self.onSelectWeek = onSelectWeek
        _monthCursor = State(initialValue: currentWeekStart.startOfMonth())
    }

    private var locale: Locale {
        Locale(identifier: language.localeIdentifier)
    }

    private var monthPlans: [WeekPlan] {
        let calendar = Calendar.current
        return weekPlans
            .filter {
                calendar.component(.year, from: $0.weekStartDate) == calendar.component(.year, from: monthCursor) &&
                calendar.component(.month, from: $0.weekStartDate) == calendar.component(.month, from: monthCursor)
            }
            .sorted { $0.weekStartDate > $1.weekStartDate }
    }

    var body: some View {
        NavigationStack {
            VStack(spacing: 14) {
                monthHeader

                if monthPlans.isEmpty {
                    Text("history_month_empty")
                        .font(.mealMoodBody)
                        .foregroundColor(.mealMoodTextSecondary)
                        .padding(.top, 24)
                } else {
                    List(monthPlans, id: \.id) { plan in
                        Button {
                            onSelectWeek(plan.weekStartDate)
                            dismiss()
                        } label: {
                            HStack {
                                VStack(alignment: .leading, spacing: 4) {
                                    Text(weekLabel(for: plan.weekStartDate))
                                        .font(.mealMoodBodyBold)
                                        .foregroundColor(.mealMoodTextPrimary)
                                    Text(plan.slots.allSatisfy { $0.dishId != nil } ? String(localized: "history_week_complete") : String(localized: "history_week_incomplete"))
                                        .font(.mealMoodCaption)
                                        .foregroundColor(.mealMoodTextSecondary)
                                }
                                Spacer()
                                Image(systemName: "chevron.right")
                                    .foregroundColor(.mealMoodTextSecondary)
                            }
                            .padding(.vertical, 4)
                        }
                        .listRowBackground(Color.mealMoodSurface)
                    }
                    .listStyle(.plain)
                    .scrollContentBackground(.hidden)
                }
            }
            .padding(.horizontal, 16)
            .padding(.top, 10)
            .background(Color.mealMoodBackground.ignoresSafeArea())
            .navigationTitle("history_title")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("tag_selector_done") { dismiss() }
                }
            }
        }
    }

    private var monthHeader: some View {
        HStack {
            Button {
                monthCursor = monthCursor.addingMonths(-1)
            } label: {
                Image(systemName: "chevron.left")
                    .foregroundColor(.mealMoodCoral)
            }

            Spacer()

            Text(monthCursor.monthYearLabel(locale: locale))
                .font(.mealMoodH3)
                .foregroundColor(.mealMoodTextPrimary)

            Spacer()

            Button {
                monthCursor = monthCursor.addingMonths(1)
            } label: {
                Image(systemName: "chevron.right")
                    .foregroundColor(.mealMoodCoral)
            }
        }
    }

    private func weekLabel(for startDate: Date) -> String {
        let endDate = startDate.addingDays(6)
        let dayFormatter = DateFormatter()
        dayFormatter.locale = locale
        dayFormatter.setLocalizedDateFormatFromTemplate("d")

        let monthFormatter = DateFormatter()
        monthFormatter.locale = locale
        monthFormatter.setLocalizedDateFormatFromTemplate("MMM")

        return "\(dayFormatter.string(from: startDate))-\(dayFormatter.string(from: endDate)) \(monthFormatter.string(from: endDate))"
    }
}
