import json
import logging
from datetime import datetime, timedelta
from typing import Optional, Tuple

from app.config import settings

logger = logging.getLogger(__name__)


class GoogleCalendarService:
    """
    Google Calendar + Google Meet integration.

    Supports two modes:

    1. Shared calendar mode (recommended):
       - Service account must be granted "Make changes to events"
         on the calendar.
       - No Domain-Wide Delegation required.
       - Cannot invite attendees (Google restriction).

    2. Domain-Wide Delegation mode:
       - Requires Workspace admin setup.
       - Allows impersonation and sending invites.
    """

    @staticmethod
    def _is_configured() -> bool:
        return bool(
            settings.google_enabled
            and settings.google_service_account_json
            and settings.google_calendar_id
        )

    @staticmethod
    def _get_calendar_client():
        from google.oauth2.service_account import Credentials
        from googleapiclient.discovery import build

        info = json.loads(settings.google_service_account_json)

        scopes = ["https://www.googleapis.com/auth/calendar"]

        creds = Credentials.from_service_account_info(
            info,
            scopes=scopes,
        )

        # Only use impersonation if explicitly configured
        if settings.google_workspace_user:
            creds = creds.with_subject(settings.google_workspace_user)

        return build("calendar", "v3", credentials=creds, cache_discovery=False)

    @staticmethod
    def create_discovery_event(
        *,
        partner_name: str,
        partner_email: str,
        scheduled_start: datetime,
        duration_minutes: int = 45,
    ) -> Tuple[Optional[str], Optional[str], Optional[str]]:
        """
        Create a Google Calendar event with optional Google Meet link.

        Returns:
            (event_id, calendar_html_link, meet_link)
        """

        if not GoogleCalendarService._is_configured():
            logger.info("GoogleCalendarService not configured.")
            return None, None, None

        try:
            service = GoogleCalendarService._get_calendar_client()

            scheduled_end = scheduled_start + timedelta(minutes=duration_minutes)

            use_attendees = bool(settings.google_workspace_user)

            event = {
                "summary": f"POU Discovery Session — {partner_name}",
                "description": (
                    "Discovery alignment session for partner onboarding and verification.\n\n"
                    f"Partner: {partner_name}\n"
                    f"Email: {partner_email}\n"
                ),
                "start": {
                    "dateTime": scheduled_start.isoformat(),
                    "timeZone": "Africa/Lagos",
                },
                "end": {
                    "dateTime": scheduled_end.isoformat(),
                    "timeZone": "Africa/Lagos",
                },
                # Let Google automatically assign Google Meet
                "conferenceData": {
                    "createRequest": {
                        "requestId": f"pou-{int(datetime.utcnow().timestamp())}"
                    }
                },
            }

            # Only add attendees if using domain-wide delegation
            if use_attendees:
                event["attendees"] = [{"email": partner_email}]

            created = (
                service.events()
                .insert(
                    calendarId=settings.google_calendar_id or "primary",
                    body=event,
                    conferenceDataVersion=1,
                    sendUpdates="all" if use_attendees else "none",
                )
                .execute()
            )

            event_id = created.get("id")
            html_link = created.get("htmlLink")

            # Extract Meet link safely
            meet_link = created.get("hangoutLink")

            if not meet_link:
                conf = created.get("conferenceData") or {}
                for ep in conf.get("entryPoints", []):
                    if ep.get("entryPointType") == "video" and ep.get("uri"):
                        meet_link = ep.get("uri")
                        break

            return event_id, html_link, meet_link

        except Exception as e:
            logger.exception("Failed to create Google Calendar/Meet event: %s", str(e))
            return None, None, None