import EventKit
import Foundation

@MainActor
final class CalendarService {
    static let shared = CalendarService()
    private let eventStore = EKEventStore()

    private init() {}

    func requestAccess() async -> Bool {
        do {
            return try await eventStore.requestFullAccessToEvents()
        } catch {
            print("Calendar access error: \(error)")
            return false
        }
    }

    func availableCalendars() -> [EKCalendar] {
        eventStore.calendars(for: .event)
    }

    func createEvent(
        slot: MealSlot,
        dishName: String,
        dishDescription: String?,
        weekStartDate: Date,
        settings: AppSettings
    ) -> String? {
        guard let calendar = resolvedCalendar(for: settings) else {
            print("Calendar sync skipped: no writable calendar available")
            return nil
        }

        let event = EKEvent(eventStore: eventStore)

        let prefix = settings.eventPrefix.isEmpty ? "" : "\(settings.eventPrefix) "
        let mealNameKey = slot.mealType == "lunch" ? "lunch" : "dinner"
        let mealName = localizedString(mealNameKey, language: settings.languageEnum.resolved())
        event.title = "\(prefix)\(mealName): \(dishName)"

        let slotDate = weekStartDate.addingDays(slot.dayOfWeek)
        let slotTime = slot.mealType == "lunch" ? settings.lunchTime : settings.dinnerTime
        event.startDate = combineDateAndTime(date: slotDate, time: slotTime)
        event.endDate = event.startDate.addingMinutes(settings.eventDuration)
        event.notes = dishDescription
        event.calendar = calendar

        if let reminder = settings.reminderMinutesBefore {
            event.addAlarm(EKAlarm(relativeOffset: -TimeInterval(reminder * 60)))
        }

        do {
            try eventStore.save(event, span: .thisEvent)
            return event.eventIdentifier
        } catch {
            print("Error saving event: \(error)")
            return nil
        }
    }

    func deleteEvent(eventId: String) {
        guard let event = eventStore.event(withIdentifier: eventId) else { return }
        do {
            try eventStore.remove(event, span: .thisEvent)
        } catch {
            print("Error deleting event: \(error)")
        }
    }

    func updateEventsTime(slots: [MealSlot], weekStartDate: Date, settings: AppSettings) {
        for slot in slots {
            guard let eventId = slot.calendarEventId,
                  let event = eventStore.event(withIdentifier: eventId),
                  event.startDate >= Date() else { continue }

            let slotDate = weekStartDate.addingDays(slot.dayOfWeek)
            let newTime = slot.mealType == "lunch" ? settings.lunchTime : settings.dinnerTime
            event.startDate = combineDateAndTime(date: slotDate, time: newTime)
            event.endDate = event.startDate.addingMinutes(settings.eventDuration)

            try? eventStore.save(event, span: .thisEvent)
        }
    }

    private func resolvedCalendar(for settings: AppSettings) -> EKCalendar? {
        if let calendarId = settings.calendarId,
           let calendar = eventStore.calendar(withIdentifier: calendarId) {
            return calendar
        }

        if let defaultCalendar = eventStore.defaultCalendarForNewEvents {
            return defaultCalendar
        }

        return eventStore.calendars(for: .event).first
    }
}
