import EventKit
import Foundation

class CalendarService: ObservableObject {
    private let eventStore = EKEventStore()
    @Published var events: [EKEvent] = []
    @Published var selectedCalendars: Set<String> = []
    @Published var availableCalendars: [EKCalendar] = []
    @Published var hasAccess = false

    init() {
        Task {
            await requestAccess()
        }
        setupNotificationObserver()
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    private func setupNotificationObserver() {
        NotificationCenter.default.addObserver(
            forName: .EKEventStoreChanged,
            object: eventStore,
            queue: .main
        ) { [weak self] _ in
            self?.handleEventStoreChanged()
        }

        NotificationCenter.default.addObserver(
            forName: .NSCalendarDayChanged,
            object: nil,
            queue: .main
        ) { [weak self] _ in
            self?.handleDayChanged()
        }
    }

    @MainActor
    private func handleEventStoreChanged() {
        loadCalendars()
        loadEvents()
    }

    @MainActor
    private func handleDayChanged() {
        loadEvents()
    }

    @MainActor
    func requestAccess() async {
        do {
            let granted = try await eventStore.requestFullAccessToEvents()
            hasAccess = granted
            if granted {
                loadCalendars()
                loadDefaultSelectedCalendars()
                loadEvents()
            }
        } catch {
            print("Calendar access error: \(error)")
            hasAccess = false
        }
    }

    @MainActor
    func loadCalendars() {
        availableCalendars = eventStore.calendars(for: .event)
    }

    @MainActor
    func loadDefaultSelectedCalendars() {
        if let savedCalendars = UserDefaults.standard.array(forKey: "selectedCalendars") as? [String] {
            selectedCalendars = Set(savedCalendars)
        } else {
            selectedCalendars = Set(availableCalendars.map { $0.calendarIdentifier })
        }
    }

    @MainActor
    func saveSelectedCalendars() {
        UserDefaults.standard.set(Array(selectedCalendars), forKey: "selectedCalendars")
        loadEvents()
    }

    @MainActor
    func loadEvents() {
        let calendar = Calendar.current
        let today = calendar.startOfDay(for: Date())

        guard let startDate = calendar.date(byAdding: .day, value: -14, to: today),
              let endDate = calendar.date(byAdding: .day, value: 14, to: today) else {
            return
        }

        let calendars = availableCalendars.filter { selectedCalendars.contains($0.calendarIdentifier) }

        let predicate = eventStore.predicateForEvents(withStart: startDate, end: endDate, calendars: calendars)
        let fetchedEvents = eventStore.events(matching: predicate)

        events = fetchedEvents.sorted { $0.startDate < $1.startDate }
    }
}
