import boto3
from github.env import exit_on_error_and_write_summary
from actions_logging.app_logging import logger


def create_client_or_exit(client_type: str, region_name: str, session: boto3.Session = None) -> boto3.client:
    if not region_name:
        exit_on_error_and_write_summary(f"Error creating {client_type} client, region name is required")
    try:
        if session:
            return session.client(client_type, region_name)
        else:
            return boto3.client(client_type, region_name)
    except Exception as e:
        exit_on_error_and_write_summary(f"Error creating {client_type} client: {e}")


def create_session(region_name: str, creds: dict = None) -> boto3.Session:
    """
    Function to create a boto3 session with the provided credentials and region name.
    :param region_name: region name to create the session in
    :param creds: dict containing the credentials
    :return: boto3.Session object
    """
    try:
        logger.info(f"Creating session with region: {region_name} and creds")
        if creds:
            if not all([creds.get('AccessKeyId'), creds.get('SecretAccessKey'), creds.get('SessionToken')]):
                raise ValueError("Error creating session, missing credentials in creds dict")
            return boto3.Session(
                aws_access_key_id=creds.get('AccessKeyId'),
                aws_secret_access_key=creds.get('SecretAccessKey'),
                aws_session_token=creds.get('SessionToken'),
                region_name=region_name)
        else:
            logger.info("no creds provided, creating session without creds")
            return boto3.Session(region_name=region_name)
    except Exception as e:
        raise RuntimeError(f"Error creating session: {e}")


def create_client_from_session(client_type: str, region_name: str, creds: dict = None) -> boto3.client:
    """
    Create a boto3 client from a session with the provided credentials and region name.
    boto3 session can give u the ability to create a client in multithread run.
    :param client_type: s3, ec2, ecs or every other valid aws service
    :param region_name: region name to create the client in
    :param creds: a dict containing the credentials
    :return: boto3.client
    """
    try:
        logger.info(f"Creating {client_type} client in region: {region_name} using session and creds")
        session = create_session(region_name, creds)
        return create_client_or_exit(client_type, region_name, session)
    except Exception as e:
        raise RuntimeError(f"Error creating client from session: {e}")
