import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from typing import Literal
from google.apps import meet_v2
from dotenv import load_dotenv
load_dotenv()

SCOPES =['https://www.googleapis.com/auth/calendar',
        "https://www.googleapis.com/auth/gmail.modify",
        "https://www.googleapis.com/auth/tasks",
        "https://www.googleapis.com/auth/meetings.space.created",
        "https://www.googleapis.com/auth/documents",
        "https://www.googleapis.com/auth/drive",
        "https://www.googleapis.com/auth/presentations",
        "https://www.googleapis.com/auth/classroom.courses",
        "https://www.googleapis.com/auth/classroom.coursework.me",
        "https://www.googleapis.com/auth/classroom.coursework.students",
        "https://www.googleapis.com/auth/classroom.courseworkmaterials",
        "https://www.googleapis.com/auth/classroom.rosters",
        "https://www.googleapis.com/auth/classroom.profile.emails",
        "https://www.googleapis.com/auth/spreadsheets"
        ]

def get_service(service_name: Literal["gmail", "calendar", "meet", "tasks", "slides", "sheets", "docs", "classroom", "drive"]):
    """
    Authenticate and return a Google Workspace service client.

    This function provides a unified way to connect to Gmail, Calendar,
    Tasks, Meet, and other Google Workspace services using a credentials file.

    Args:
        service_name (Literal["gmail", "calendar", "meet", "tasks", "slides", "sheets", "docs", "classroom", "keep"]):

            The name of the service you want to access.

            - "gmail": Gmail service.
            - "calendar": Google Calendar service.
            - "meet": Google Meet service.
            - "tasks": Google Tasks service.
            - "drive" Google Drive service.
            - "slides": Google Slides service.
            - "sheets": Google Sheets service.
            - "docs": Google Docs service.
            - "classroom": Google Classroom service.
    Returns:
        Any | SpacesServiceAsyncClient: An authenticated service client object
        for the requested Google Workspace service.

    Raises:
        ValueError: If an unsupported service name is provided.
        Exception: For errors during authentication or service creation.
    """
    try:
        creds = None
        credentials_path = os.getenv("GOOGLE_CREDENTIALS_PATH", "credentials.json")
        if os.path.exists("token.json"):
            creds = Credentials.from_authorized_user_file("token.json", SCOPES)
        if not creds or not creds.valid:
            if creds and creds.expired and creds.refresh_token:
                creds.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file(
                    credentials_path, SCOPES
                )
                creds = flow.run_local_server(port=0)
            with open("token.json", "w") as token:
                token.write(creds.to_json())
        if service_name== 'calendar':
            return build("calendar", "v3", credentials= creds)
        elif service_name== 'gmail':
            return build("gmail", "v1", credentials= creds)
        elif service_name== 'tasks':
            return build("tasks", "v1", credentials= creds)
        elif service_name == "meet":
            return meet_v2.SpacesServiceAsyncClient(credentials= creds)
        elif service_name == "docs":
            return build("docs", "v1", credentials=creds)
        elif service_name == "drive":
            return build("drive", "v3", credentials=creds)
        elif service_name == "slides":
            return build("slides", "v1", credentials=creds)
        elif service_name == "sheets":
            return build("sheets", "v4", credentials=creds)
        elif service_name == "classroom":
            return build("classroom", "v1", credentials= creds)
        else:
            raise ValueError(f"Unsupported service: {service_name}")
    except Exception as e:
        raise Exception(f"Error in getting service for {service_name}---Error is: {e}")

async def aget_service(service_name: Literal["meet"]):
    """
    Async Function to Authenticate and return a Google Workspace service client.

    This function provides authentication just for Google meet. Because for meet we have async instance.

    Args:
        service_name (Literal["gmail", "calendar", "meet", "tasks", "slides", "sheets", "docs", "classroom", "keep"]):
            The name of the service you want to access.
            - "gmail": Gmail service.
            - "calendar": Google Calendar service.
            - "meet": Google Meet service.
            - "tasks": Google Tasks service.
            - "slides": Google Slides service.
            - "sheets": Google Sheets service.
            - "docs": Google Docs service.
            - "classroom": Google Classroom service.
            - "keep": Google Keep Notes service.
    Returns:
        Any | SpacesServiceAsyncClient: An authenticated service client object
        for the requested Google Workspace service.

    Raises:
        ValueError: If an unsupported service name is provided.
        Exception: For errors during authentication or service creation.
    """
    try:
        creds = None
        credentials_path = os.getenv("GOOGLE_CREDENTIALS_PATH", "credentials.json")
        if os.path.exists("token.json"):
            creds = Credentials.from_authorized_user_file("token.json", SCOPES)
        if not creds or not creds.valid:
            if creds and creds.expired and creds.refresh_token:
                creds.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file(
                    credentials_path, SCOPES
                )
                creds = flow.run_local_server(port=0)
            with open("token.json", "w") as token:
                token.write(creds.to_json())
        if service_name == "meet":
            return meet_v2.SpacesServiceAsyncClient(credentials= creds)
        else:
            raise ValueError(f"Unsupported service: {service_name}")
    except Exception as e:
        raise Exception(f"Error in getting service for {service_name}---Error is: {e}")
