#!/usr/bin/env python3
"""Morning briefing - reads APPLE_EMAIL and APPLE_APP_PASSWORD from env."""
import caldav, datetime, random, feedparser, json, os, sys

# Import personalized compliments for Caoil
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from caoil_compliments import COMPLIMENTS_POOL

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

NEWS_FEEDS = [
    "https://feeds.bbci.co.uk/news/rss.xml",
    "https://feeds.bbci.co.uk/news/technology/rss.xml",
    "https://rss.cnn.com/rss/edition.rss",
    "https://feeds.arstechnica.com/arstechnica/index",
]

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()  # deduplication

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

            # Strategy 1: search with expand=True (recurring events expanded)
            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: search without expand (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 events we found
            for event in cal_events:
                try:
                    vevent = event.vobject_instance.vevent
                    raw_summary = vevent.summary
                    if hasattr(raw_summary, 'value'):
                        summary = raw_summary.value
                    else:
                        summary = 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}"

                    # Deduplicate
                    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)
                    continue

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

        # Sort: timed events first, then all-day
        def sort_key(item):
            t = item[0]
            return (0 if t != "All day" else 1, t)
        all_events.sort(key=sort_key)

        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}*"

def get_news_headlines():
    articles = []
    for feed_url in NEWS_FEEDS:
        try:
            feed = feedparser.parse(feed_url)
            for entry in feed.entries[:3]:
                title = entry.get("title", "").strip()
                link = entry.get("link", "").strip()
                if title and len(title) > 10 and link:
                    articles.append((title, link))
        except Exception:
            continue
    if not articles:
        return "*Couldn't fetch news today.*"
    selected = random.sample(articles, min(3, len(articles)))
    return "\n".join(f"• {title}\n  {link}" for title, link in selected)

def get_stock_prices():
    """Fetch current prices from Yahoo Finance."""
    import urllib.request

    tickers = {
        "TSLA": "Tesla",
        "NVDA": "NVIDIA",
        "AAPL": "Apple",
        "AMD": "AMD",
        "MSFT": "Microsoft",
        "GOOGL": "Alphabet",
        "META": "Meta",
        "AMZN": "Amazon",
        "BTC-USD": "Bitcoin",
    }
    results = []
    headers = {"User-Agent": "Mozilla/5.0"}

    for ticker, name in tickers.items():
        url = f"https://query1.finance.yahoo.com/v8/finance/chart/{ticker}"
        req = urllib.request.Request(url, headers=headers)
        try:
            with urllib.request.urlopen(req, timeout=15) as resp:
                data = json.loads(resp.read().decode())
                result = data.get("chart", {}).get("result", [{}])[0]
                price = result.get("meta", {}).get("regularMarketPrice")
                if price is None:
                    price = result.get("meta", {}).get("previousClose")
                if price is not None:
                    results.append(f"• {name} ({ticker}): ${float(price):,.2f}")
                else:
                    results.append(f"• {name} ({ticker}): *unavailable*")
        except Exception:
            results.append(f"• {name} ({ticker}): *unavailable*")

    return "\n".join(results) if results else "*Couldn't fetch stock prices today.*"

def get_daily_compliment():
    return random.choice(COMPLIMENTS_POOL)

def main():
    events = get_today_events()
    news = get_news_headlines()
    stocks = get_stock_prices()
    compliment = get_daily_compliment()
    today_str = datetime.date.today().strftime("%A, %B %d")
    message = f"""Good morning, Sage!

Today is {today_str}.

📅 Your day:
{events}

🌍 Today's headlines:
{news}

📈 Stock prices:
{stocks}

💝 For her:
{compliment}

Have a great day!"""
    print(message)

if __name__ == "__main__":
    main()
