from base64 import urlsafe_b64encode
from datetime import datetime, timedelta, timezone
import hashlib
from urllib.parse import urlencode

import httpx

from app.core.config import get_settings


GOOGLE_AUTHORIZATION_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth"
GOOGLE_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token"
GOOGLE_USERINFO_ENDPOINT = "https://openidconnect.googleapis.com/v1/userinfo"
GOOGLE_DOCS_ENDPOINT = "https://docs.googleapis.com/v1"
GOOGLE_SHEETS_ENDPOINT = "https://sheets.googleapis.com/v4"
GOOGLE_DRIVE_ENDPOINT = "https://www.googleapis.com/drive/v3"


def utc_now() -> datetime:
    return datetime.now(timezone.utc)


def utc_now_isoformat() -> str:
    return utc_now().isoformat()


def expires_at_from_seconds(expires_in: int | float) -> str:
    return (utc_now() + timedelta(seconds=float(expires_in))).isoformat()


def is_google_workspace_configured() -> bool:
    settings = get_settings()
    return bool(settings.google_workspace_client_id and settings.google_workspace_client_secret)


def build_google_code_challenge(code_verifier: str) -> str:
    digest = hashlib.sha256(code_verifier.encode("utf-8")).digest()
    return urlsafe_b64encode(digest).decode("utf-8").rstrip("=")


def build_google_authorization_url(*, state: str, code_challenge: str, scopes: list[str] | None = None) -> str:
    settings = get_settings()
    params = {
        "client_id": settings.google_workspace_client_id,
        "redirect_uri": settings.google_workspace_redirect_uri,
        "response_type": "code",
        "scope": " ".join(scopes or settings.google_workspace_scopes_list),
        "access_type": "offline",
        "include_granted_scopes": "true",
        "prompt": "consent",
        "state": state,
        "code_challenge": code_challenge,
        "code_challenge_method": "S256",
    }
    return f"{GOOGLE_AUTHORIZATION_ENDPOINT}?{urlencode(params)}"


async def exchange_google_code_for_tokens(*, code: str, code_verifier: str) -> dict[str, object]:
    settings = get_settings()
    async with httpx.AsyncClient(timeout=settings.google_workspace_request_timeout_seconds) as client:
        response = await client.post(
            GOOGLE_TOKEN_ENDPOINT,
            data={
                "client_id": settings.google_workspace_client_id,
                "client_secret": settings.google_workspace_client_secret,
                "redirect_uri": settings.google_workspace_redirect_uri,
                "grant_type": "authorization_code",
                "code": code,
                "code_verifier": code_verifier,
            },
        )
        response.raise_for_status()
        return response.json()


async def refresh_google_access_token(refresh_token: str) -> dict[str, object]:
    settings = get_settings()
    async with httpx.AsyncClient(timeout=settings.google_workspace_request_timeout_seconds) as client:
        response = await client.post(
            GOOGLE_TOKEN_ENDPOINT,
            data={
                "client_id": settings.google_workspace_client_id,
                "client_secret": settings.google_workspace_client_secret,
                "grant_type": "refresh_token",
                "refresh_token": refresh_token,
            },
        )
        response.raise_for_status()
        return response.json()


async def fetch_google_account_email(access_token: str) -> str | None:
    settings = get_settings()
    async with httpx.AsyncClient(timeout=settings.google_workspace_request_timeout_seconds) as client:
        response = await client.get(
            GOOGLE_USERINFO_ENDPOINT,
            headers={"Authorization": f"Bearer {access_token}"},
        )
        response.raise_for_status()
        payload = response.json()
        email = payload.get("email")
        return str(email) if email else None
