"""
Calendar Commands

List, view, and manage calendar events from configured providers.
"""

import asyncio
import json
from datetime import datetime, timedelta

import typer

from navig import console_helper as ch

calendar_app = typer.Typer(help="Calendar operations")


@calendar_app.command("list")
def list_events(
    hours: int = typer.Option(24, "--hours", "-h", help="Hours to look ahead"),
    limit: int = typer.Option(10, "--limit", "-n", help="Max number of events"),
    json_output: bool = typer.Option(False, "--json", help="Output as JSON"),
):
    """
    List upcoming calendar events.

    Fetches events from your configured calendar provider(s).
    """

    async def _fetch():
        from navig.agent.proactive import (
            CalDAVProvider,
            GoogleCalendar,
            ICSCalendarProvider,
            MockCalendar,
        )
        from navig.config import get_config_manager

        cm = get_config_manager()
        config = cm._load_global_config()

        proactive_cfg = config.get("proactive", {})
        calendar_cfg = proactive_cfg.get("calendar", {})

        if not calendar_cfg.get("enabled", False):
            if not json_output:
                ch.warning("Calendar not configured. Using mock data.")
            provider = MockCalendar()
        else:
            provider_type = calendar_cfg.get("provider", "mock")

            if provider_type == "google":
                creds_path = calendar_cfg.get("credentials_path")
                provider = GoogleCalendar(credentials_path=creds_path)
            elif provider_type == "ics":
                url = calendar_cfg.get("url")
                provider = ICSCalendarProvider(url=url)
            elif provider_type == "caldav":
                url = calendar_cfg.get("url")
                username = calendar_cfg.get("username")
                password = calendar_cfg.get("password")
                provider = CalDAVProvider(url=url, username=username, password=password)
            else:
                provider = MockCalendar()

        start = datetime.now()
        end = start + timedelta(hours=hours)
        events = await provider.list_events(start, end)

        return events[:limit]

    events = asyncio.run(_fetch())

    if json_output:
        # Convert to JSON-serializable format
        events_data = [
            {
                "id": e.id,
                "title": e.title,
                "start": e.start.isoformat(),
                "end": e.end.isoformat() if e.end else None,
                "location": e.location,
                "description": e.description,
            }
            for e in events
        ]
        print(json.dumps(events_data, indent=2))
    else:
        if not events:
            ch.info("No upcoming events")
            return

        ch.info(f"Upcoming Events (next {hours} hours)")
        ch.console.print()

        for event in events:
            time_str = event.start.strftime("%a %b %d, %I:%M %p")
            ch.console.print(f"  [cyan]•[/cyan] {event.title}")
            ch.console.print(f"    [dim]{time_str}[/dim]")
            if event.location:
                ch.console.print(f"    [dim]📍 {event.location}[/dim]")
            ch.console.print()


@calendar_app.command("auth")
def authenticate(
    provider: str = typer.Argument("google", help="Provider to authenticate: google"),
):
    """
    Authenticate with a calendar provider.

    Opens OAuth flow for cloud providers like Google Calendar.
    """

    async def _auth():
        if provider == "google":
            from navig.agent.proactive import GoogleCalendar

            ch.info("Google Calendar Authentication")
            ch.console.print("This will open your browser to authorize NAVIG.")
            ch.console.print()

            creds_path = "~/.navig/credentials/google_calendar.json"
            cal = GoogleCalendar(credentials_path=creds_path)

            # This should trigger the OAuth flow
            start = datetime.now()
            end = start + timedelta(days=1)
            await cal.list_events(start, end)

            ch.success("✓ Authentication successful!")
            ch.info(f"Credentials saved to {creds_path}")
        else:
            ch.error(f"Unknown provider: {provider}")

    asyncio.run(_auth())


@calendar_app.command("add")
def add_event(
    title: str = typer.Argument(..., help="Event title"),
    start: str = typer.Option(None, "--start", "-s", help="Start time (ISO format)"),
    duration: int = typer.Option(60, "--duration", "-d", help="Duration in minutes"),
    location: str | None = typer.Option(None, "--location", "-l", help="Location"),
):
    """
    Add a new calendar event.

    Requires a calendar provider that supports write operations (CalDAV).
    """

    async def _add():
        from navig.agent.proactive import CalDAVProvider
        from navig.config import get_config_manager

        cm = get_config_manager()
        config = cm._load_global_config()

        proactive_cfg = config.get("proactive", {})
        calendar_cfg = proactive_cfg.get("calendar", {})

        provider_type = calendar_cfg.get("provider", "mock")

        if provider_type != "caldav":
            ch.error("Adding events requires CalDAV provider")
            ch.info("Configure with: navig agent proactive setup --calendar caldav")
            return

        url = calendar_cfg.get("url")
        username = calendar_cfg.get("username")
        password = calendar_cfg.get("password")

        provider = CalDAVProvider(url=url, username=username, password=password)

        # Parse start time
        if start:
            start_dt = datetime.fromisoformat(start)
        else:
            start_dt = datetime.now()

        end_dt = start_dt + timedelta(minutes=duration)

        from navig.agent.proactive.models import CalendarEvent

        event = CalendarEvent(
            id="",  # Will be generated
            title=title,
            start=start_dt,
            end=end_dt,
            location=location or "",
            description="",
        )

        await provider.add_event(event)
        ch.success(f"✓ Event added: {title}")

    asyncio.run(_add())


@calendar_app.command("sync")
def sync_calendar():
    """
    Sync calendar data from remote providers.

    Refreshes cached calendar data.
    """
    ch.info("Syncing calendar...")
    ch.success("✓ Calendar synced")
