"""Google Calendar API integration via raw httpx — multi-account, shared calendars."""

from typing import Any
from uuid import uuid4

import httpx

from fliiq.runtime.google_auth import get_access_token

BASE_URL = "https://www.googleapis.com/calendar/v3"


async def handler(params: dict) -> dict:
    """Handle Google Calendar operations."""
    action = params["action"]
    calendar_account = params.get("calendar_account")
    calendar_id = params.get("calendar_id", "primary")

    try:
        _, access_token = await get_access_token(calendar_account)
        headers = {
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json",
        }

        async with httpx.AsyncClient(timeout=30) as client:
            if action == "list_calendars":
                return await _list_calendars(client, headers)
            elif action == "list_events":
                return await _list_events(client, headers, params, calendar_id)
            elif action == "create_event":
                return await _create_event(client, headers, params, calendar_id)
            elif action == "update_event":
                return await _update_event(client, headers, params, calendar_id)
            elif action == "delete_event":
                return await _delete_event(client, headers, params, calendar_id)
            else:
                return {
                    "success": False,
                    "message": f"Unknown action: {action}",
                    "data": {},
                }
    except ValueError:
        raise  # Credential/token errors propagate to user
    except httpx.HTTPStatusError as e:
        error_msg = f"Google Calendar API error: {e.response.status_code}"
        try:
            error_data = e.response.json()
            if "error" in error_data:
                detail = error_data["error"]
                if isinstance(detail, dict):
                    error_msg += f" - {detail.get('message', '')}"
                else:
                    error_msg += f" - {detail}"
        except Exception:
            pass
        return {"success": False, "message": error_msg, "data": {}}
    except Exception as e:
        return {"success": False, "message": f"Error: {e}", "data": {}}


async def _list_calendars(
    client: httpx.AsyncClient, headers: dict
) -> dict:
    """List all calendars accessible to the authenticated user."""
    resp = await client.get(
        f"{BASE_URL}/users/me/calendarList",
        headers=headers,
    )
    resp.raise_for_status()

    data = resp.json()
    calendars = []
    for item in data.get("items", []):
        calendars.append({
            "id": item["id"],
            "summary": item.get("summary", ""),
            "description": item.get("description", ""),
            "access_role": item.get("accessRole", ""),
            "primary": item.get("primary", False),
        })

    return {
        "success": True,
        "message": f"Found {len(calendars)} calendar(s)",
        "data": {"calendars": calendars},
    }


async def _list_events(
    client: httpx.AsyncClient,
    headers: dict,
    params: dict,
    calendar_id: str,
) -> dict:
    """List events in a time range."""
    query_params: dict[str, Any] = {
        "singleEvents": "true",
        "orderBy": "startTime",
        "maxResults": params.get("max_results", 50),
    }
    if params.get("time_min"):
        query_params["timeMin"] = params["time_min"]
    if params.get("time_max"):
        query_params["timeMax"] = params["time_max"]

    resp = await client.get(
        f"{BASE_URL}/calendars/{calendar_id}/events",
        headers=headers,
        params=query_params,
    )
    resp.raise_for_status()

    data = resp.json()
    events = []
    for item in data.get("items", []):
        start = item.get("start", {})
        end = item.get("end", {})
        event_data: dict[str, Any] = {
            "id": item["id"],
            "summary": item.get("summary", "(No title)"),
            "start": start.get("dateTime") or start.get("date", ""),
            "end": end.get("dateTime") or end.get("date", ""),
            "attendees": [a["email"] for a in item.get("attendees", [])],
            "location": item.get("location", ""),
            "description": item.get("description", ""),
            "status": item.get("status", ""),
            "htmlLink": item.get("htmlLink", ""),
        }
        if item.get("hangoutLink"):
            event_data["hangoutLink"] = item["hangoutLink"]
        events.append(event_data)

    return {
        "success": True,
        "message": f"Found {len(events)} event(s)",
        "data": {"events": events},
    }


async def _create_event(
    client: httpx.AsyncClient,
    headers: dict,
    params: dict,
    calendar_id: str,
) -> dict:
    """Create a new calendar event."""
    body: dict[str, Any] = {
        "summary": params["summary"],
        "start": {"dateTime": params["start"]},
        "end": {"dateTime": params["end"]},
    }
    if params.get("description"):
        body["description"] = params["description"]
    if params.get("location"):
        body["location"] = params["location"]
    if params.get("attendees"):
        body["attendees"] = [{"email": e} for e in params["attendees"]]

    query_params: dict[str, Any] = {"sendUpdates": "all"}
    if params.get("add_google_meet"):
        body["conferenceData"] = {
            "createRequest": {
                "requestId": f"fliiq-{uuid4().hex[:12]}",
                "conferenceSolutionKey": {"type": "hangoutsMeet"},
            }
        }
        query_params["conferenceDataVersion"] = 1

    resp = await client.post(
        f"{BASE_URL}/calendars/{calendar_id}/events",
        headers=headers,
        json=body,
        params=query_params,
    )
    resp.raise_for_status()

    event = resp.json()
    data: dict[str, Any] = {
        "id": event["id"],
        "summary": event.get("summary", ""),
        "htmlLink": event.get("htmlLink", ""),
        "start": event.get("start", {}).get("dateTime", ""),
        "end": event.get("end", {}).get("dateTime", ""),
    }
    if event.get("hangoutLink"):
        data["hangoutLink"] = event["hangoutLink"]
    return {"success": True, "message": f"Created event '{event.get('summary', '')}'", "data": data}


async def _update_event(
    client: httpx.AsyncClient,
    headers: dict,
    params: dict,
    calendar_id: str,
) -> dict:
    """Update an existing event via PATCH."""
    event_id = params["event_id"]
    body: dict[str, Any] = {}

    if params.get("summary"):
        body["summary"] = params["summary"]
    if params.get("description"):
        body["description"] = params["description"]
    if params.get("location"):
        body["location"] = params["location"]
    if params.get("start"):
        body["start"] = {"dateTime": params["start"]}
    if params.get("end"):
        body["end"] = {"dateTime": params["end"]}
    if params.get("attendees"):
        body["attendees"] = [{"email": e} for e in params["attendees"]]

    query_params: dict[str, Any] = {"sendUpdates": "all"}
    if params.get("add_google_meet"):
        body["conferenceData"] = {
            "createRequest": {
                "requestId": f"fliiq-{uuid4().hex[:12]}",
                "conferenceSolutionKey": {"type": "hangoutsMeet"},
            }
        }
        query_params["conferenceDataVersion"] = 1

    if not body:
        return {
            "success": False,
            "message": "No fields to update. Provide: summary, description, location,"
            " start, end, attendees, or add_google_meet.",
            "data": {},
        }

    resp = await client.patch(
        f"{BASE_URL}/calendars/{calendar_id}/events/{event_id}",
        headers=headers,
        json=body,
        params=query_params,
    )
    resp.raise_for_status()

    event = resp.json()
    data: dict[str, Any] = {
        "id": event["id"],
        "summary": event.get("summary", ""),
    }
    if event.get("hangoutLink"):
        data["hangoutLink"] = event["hangoutLink"]
    return {"success": True, "message": f"Updated event '{event.get('summary', '')}'", "data": data}


async def _delete_event(
    client: httpx.AsyncClient,
    headers: dict,
    params: dict,
    calendar_id: str,
) -> dict:
    """Delete a calendar event."""
    event_id = params["event_id"]

    resp = await client.delete(
        f"{BASE_URL}/calendars/{calendar_id}/events/{event_id}",
        headers=headers,
        params={"sendUpdates": "all"},
    )
    resp.raise_for_status()

    return {
        "success": True,
        "message": f"Deleted event {event_id}",
        "data": {"deleted_event_id": event_id},
    }
