import json
import logging
from typing import TYPE_CHECKING

from google.oauth2 import service_account
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

from src.core.config import settings

if TYPE_CHECKING:
    from src.group_settings.models import GroupConfig

logger = logging.getLogger(__name__)

SCOPES = ["https://www.googleapis.com/auth/admin.directory.group.readonly",
          "https://www.googleapis.com/auth/admin.directory.group.member.readonly"]


# ---------------------------------------------------------------------------
# Internal helpers
# ---------------------------------------------------------------------------

def _build_service(group_config: "GroupConfig | None" = None):
    """Build a Google Directory API service using group-specific or global credentials."""
    from src.core.encryption import decrypt

    # Prefer DB credentials over env vars
    if group_config and group_config.service_account_json_enc:
        sa_json_str = decrypt(group_config.service_account_json_enc)
        sa_info = json.loads(sa_json_str)
        admin_email = group_config.google_admin_email or settings.google_admin_email
        logger.warning(f"DEBUG: Building Google service with DB credentials for admin: {admin_email}")
        creds = service_account.Credentials.from_service_account_info(
            sa_info,
            scopes=SCOPES,
            subject=admin_email,
        )
    elif settings.google_service_account_file:
        logger.warning(f"DEBUG: Building Google service with ENV credentials for admin: {settings.google_admin_email}")
        creds = service_account.Credentials.from_service_account_file(
            settings.google_service_account_file,
            scopes=SCOPES,
            subject=settings.google_admin_email,
        )
    else:
        logger.warning("No service account credentials configured (DB or env). Returning None.")
        return None

    return build("admin", "directory_v1", credentials=creds)


def _resolve_group_email(group_config: "GroupConfig | None") -> str | None:
    """Resolve the Google Group email from DB config or env var fallback."""
    if group_config:
        return group_config.group_email
    return settings.google_group_email


# ---------------------------------------------------------------------------
# Public API
# ---------------------------------------------------------------------------

def check_user_in_group(
    user_email: str,
    group_config: "GroupConfig | None" = None,
) -> bool:
    """
    Checks if a user is a member (any role) of the configured Google Group.
    Returns False if there is a misconfiguration or the user is not in the group.
    """
    group_email = _resolve_group_email(group_config)
    if not group_email:
        logger.warning("No group_email configured. Group check disabled, returning False.")
        return False

    try:
        service = _build_service(group_config)
        if service is None:
            return False

        logger.warning(f"DEBUG: Checking membership for {user_email} in group {group_email}")
        logger.warning(f"DEBUG: Checking membership for {user_email} in group {group_email}")
        try:
            service.members().get(
                groupKey=group_email,
                memberKey=user_email
            ).execute()
            return True
        except HttpError as e:
            if e.resp.status == 404:
                return False
            raise e

    except HttpError as e:
        logger.error(f"Google API HttpError when checking group membership: {e}")
        return False
    except Exception as e:
        logger.error(f"Unexpected error when checking Google Group membership: {e}")
        return False


def get_user_role_in_group(
    user_email: str,
    group_config: "GroupConfig | None" = None,
) -> str | None:
    """
    Returns the user's role in the group: 'OWNER', 'MANAGER', 'MEMBER', or None.
    None means the user is not a member, or an error occurred.
    """
    group_email = _resolve_group_email(group_config)
    if not group_email:
        return None

    try:
        service = _build_service(group_config)
        if service is None:
            return None

        result = service.members().get(
            groupKey=group_email,
            memberKey=user_email,
        ).execute()
        return result.get("role")  # 'OWNER', 'MANAGER', or 'MEMBER'

    except HttpError as e:
        if e.resp.status == 404:
            return None  # not a member
        logger.error(f"Google API HttpError when checking role: {e}")
        return None
    except Exception as e:
        logger.error(f"Unexpected error when checking group role: {e}")
        return None


def is_group_admin(
    user_email: str,
    group_config: "GroupConfig | None" = None,
) -> bool:
    """Returns True if the user is an OWNER or MANAGER of the Google Group."""
    role = get_user_role_in_group(user_email, group_config)
    return role in ("OWNER", "MANAGER")
