import SwiftUI
import SwiftData
import EventKit

@MainActor
final class SettingsViewModel: ObservableObject {
    @Published var availableCalendars: [EKCalendar] = []
    @Published var showCalendarPermissionAlert: Bool = false
    @Published var showToast: Bool = false
    @Published var toastMessage: String = ""

    var appVersion: String {
        Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "-"
    }

    var appBuild: String {
        Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? "-"
    }

    func loadCalendars() {
        availableCalendars = CalendarService.shared.availableCalendars()
    }

    @discardableResult
    func ensureValidCalendarSelection(settings: AppSettings) -> Bool {
        loadCalendars()

        guard !availableCalendars.isEmpty else {
            settings.calendarId = nil
            settings.syncEnabled = false
            showToastMessage(String(localized: "toast_calendar_unavailable"))
            return false
        }

        if let selected = settings.calendarId,
           availableCalendars.contains(where: { $0.calendarIdentifier == selected }) {
            return true
        }

        settings.calendarId = availableCalendars.first?.calendarIdentifier
        return true
    }

    func requestCalendarAccess() async -> Bool {
        let granted = await CalendarService.shared.requestAccess()
        if !granted {
            showCalendarPermissionAlert = true
        } else {
            loadCalendars()
        }
        return granted
    }

    func openSystemSettings() {
        if let url = URL(string: UIApplication.openSettingsURLString) {
            UIApplication.shared.open(url)
        }
    }

    func updateCalendarEvents(settings: AppSettings, plan: WeekPlan?) {
        guard let plan = plan, settings.syncEnabled else { return }
        CalendarService.shared.updateEventsTime(
            slots: plan.slots,
            weekStartDate: plan.weekStartDate,
            settings: settings
        )
    }

    func resetAllData(context: ModelContext) {
        do {
            // WeekPlan cascades MealSlot, so deleting both can corrupt the reset flow.
            try deleteAll(of: WeekPlan.self, in: context)
            try deleteAll(of: Dish.self, in: context)
            try deleteAll(of: Tag.self, in: context)
            DefaultDataService.createDefaultTags(context: context, saveImmediately: false)

            let settingsDescriptor = FetchDescriptor<AppSettings>()
            if let existingSettings = try context.fetch(settingsDescriptor).first {
                resetSettings(existingSettings)
            } else {
                DefaultDataService.createDefaultSettings(context: context)
                if let createdSettings = try context.fetch(settingsDescriptor).first {
                    resetSettings(createdSettings)
                }
            }

            try context.save()
        } catch {
            #if DEBUG
            print("Failed to reset all data: \(error)")
            #endif
        }
    }

    private func deleteAll<T: PersistentModel>(of type: T.Type, in context: ModelContext) throws {
        let descriptor = FetchDescriptor<T>()
        let models = try context.fetch(descriptor)
        for model in models {
            context.delete(model)
        }
    }

    private func showToastMessage(_ message: String) {
        toastMessage = message
        withAnimation(.easeInOut(duration: 0.2)) {
            showToast = true
        }
    }

    private func resetSettings(_ settings: AppSettings) {
        let defaults = AppSettings()
        settings.mealWindows = defaults.mealWindows
        settings.includeWeekends = defaults.includeWeekends
        settings.language = defaults.language
        settings.calendarId = defaults.calendarId
        settings.syncEnabled = defaults.syncEnabled
        settings.syncMode = defaults.syncMode
        settings.lunchTime = defaults.lunchTime
        settings.dinnerTime = defaults.dinnerTime
        settings.eventDuration = defaults.eventDuration
        settings.eventPrefix = defaults.eventPrefix
        settings.reminderMinutesBefore = defaults.reminderMinutesBefore
        settings.iCloudSyncEnabled = false
        settings.onboardingCompleted = false
    }
}
