#!/usr/bin/env python3
"""Robust Apple CalDAV calendar fetcher with fallback strategies.

This script demonstrates the multi-strategy approach used in the
morning briefing system. It fetches events from ALL calendars on an
Apple iCloud account, handling recurring events, shared calendars,
and calendars that don't respond to standard search queries.

Environment:
  APPLE_EMAIL and APPLE_APP_PASSWORD must be set in env or .env file.
"""
import caldav
import datetime
import os
import sys

CALDAV_URL = "https://caldav.icloud.com"
APPLE_EMAIL = os.environ.get("APPLE_EMAIL", "")
APPLE_APP_PASSWORD=*** "")

def get_today_events():
    if not APPLE_EMAIL or not APPLE_APP_PASSWORD:
        return "*Calendar not configured.*"
    try:
        client = caldav.DAVClient(url=CALDAV_URL, username=APPLE_EMAIL, password=APPLE_APP_PASSWORD)
        principal = client.principal()
        calendars = principal.calendars()
        if not calendars:
            return "*No calendars found.*"

        today = datetime.date.today()
        tomorrow = today + datetime.timedelta(days=1)
        all_events = []
        seen_events = set()

        for calendar in calendars:
            cal_name = calendar.get_display_name() if hasattr(calendar, 'get_display_name') else str(calendar)
            cal_events = []

            # Strategy 1: expand recurring events
            try:
                events = calendar.search(start=today, end=tomorrow, event=True, expand=True)
                cal_events.extend(events)
            except Exception as e:
                print(f"[{cal_name}] expand=True failed: {e}", file=sys.stderr)

            # Strategy 2: raw recurring entries
            if not cal_events:
                try:
                    events = calendar.search(start=today, end=tomorrow, event=True)
                    cal_events.extend(events)
                except Exception as e:
                    print(f"[{cal_name}] expand=False failed: {e}", file=sys.stderr)

            # Strategy 3: list all events and filter client-side
            if not cal_events:
                try:
                    events = calendar.events()
                    for event in events:
                        try:
                            vevent = event.vobject_instance.vevent
                            dtstart = getattr(vevent, 'dtstart', None)
                            if dtstart and dtstart.value:
                                dt = dtstart.value
                                if isinstance(dt, datetime.datetime):
                                    if today <= dt.date() < tomorrow:
                                        cal_events.append(event)
                                elif isinstance(dt, datetime.date):
                                    if today <= dt < tomorrow:
                                        cal_events.append(event)
                        except Exception:
                            continue
                except Exception as e:
                    print(f"[{cal_name}] events() failed: {e}", file=sys.stderr)

            # Parse and deduplicate
            for event in cal_events:
                try:
                    vevent = event.vobject_instance.vevent
                    raw_summary = vevent.summary
                    summary = raw_summary.value if hasattr(raw_summary, 'value') else str(raw_summary)
                    if summary.startswith("<SUMMARY{") and summary.endswith(">"):
                        summary = summary[len("<SUMMARY{"):summary.rfind("}")]

                    dtstart = getattr(vevent, "dtstart", None)
                    time_str = 'All day'
                    event_key = summary
                    if dtstart:
                        st = dtstart.value
                        if isinstance(st, datetime.datetime):
                            time_str = st.strftime('%H:%M')
                            event_key = f"{time_str}|{summary}"
                        elif isinstance(st, datetime.date):
                            event_key = f"allday|{summary}"

                    if event_key in seen_events:
                        continue
                    seen_events.add(event_key)
                    all_events.append((time_str, summary))
                except Exception as e:
                    print(f"[{cal_name}] Parse error: {e}", file=sys.stderr)

        if not all_events:
            return "*No events scheduled for today.*"

        # Sort: timed first, then all-day
        all_events.sort(key=lambda item: (0 if item[0] != 'All day' else 1, item[0]))
        return "\n".join(f"• {time_str}: {summary}" for time_str, summary in all_events)
    except Exception as e:
        return f"*Couldn't fetch calendar: {e}*"


if __name__ == "__main__":
    print(get_today_events())
