from lambdas.constants import NON_STANDARD_LAMBDA_NAMING
from actions_logging.app_logging import logger
import boto3
from github.env import exit_on_error_and_write_summary
from aws.constants import PRODUCTION, PROD_ENVS
from lambdas.constants import LAMBDA_VERSION_TAG
from aws.lambdas.lambda_api import get_lambda_tags

def get_lambda_function_name(svc_name: str, env_name: str) ->str:
    if not env_name:
        raise ValueError(f"environment name for lambda must be provided")
    if not svc_name:
        raise ValueError(f"service name for lambda must be provided")
    lambda_env_name = env_name
    if env_name in PROD_ENVS:
        lambda_env_name = PRODUCTION
    for lambda_svc_name, corrected_lambda_name in NON_STANDARD_LAMBDA_NAMING.items():
        if lambda_svc_name in svc_name:
            return f"{corrected_lambda_name}-{lambda_env_name}"
    name = f'{lambda_env_name}-{svc_name}'
    return name 

def list_lambda_functions(aws_region: str) ->str:
    if not aws_region:
        raise ValueError(f"region for lambda must be provided")
    lambda_client = boto3.client('lambda', region_name=aws_region)
    functions = []
    paginator = lambda_client.get_paginator('list_functions')
    logger.debug("fetching list of lambda functions")
    for page in paginator.paginate():
        functions.extend(page['Functions'])
    logger.debug(f"retrieved {len(functions)} lambda functions")    
    return functions

def find_lambda_function(env_name: str, svc_name: str, aws_region: str) ->str:
    if not env_name:
        raise ValueError(f"environment name for lambda must be provided")
    if not svc_name:
        raise ValueError(f"service name for lambda must be provided")
    if not aws_region:
        raise ValueError(f"region for lambda must be provided")
    functions = list_lambda_functions(aws_region)
    logger.debug(f"Functions in the region are: {functions} ")
    for function in functions:
        function_name = function['FunctionName']
        if env_name in function_name and svc_name in function_name:
            return function_name
    exit_on_error_and_write_summary(f'No function found in the env {env_name} by name {svc_name} in region {aws_region}')


def check_if_lambda_exists_and_get_version_tag(lambda_name_to_check, region) -> tuple[bool, str]:
    """
    this function get a lambda name and region and check if the lambda exists and has the tag LAMBDA_VERSION_TAG
    :param lambda_name_to_check:
    :param region:
    :return:
    """
    logger.debug(f"Will try to Get tags for lambda {lambda_name_to_check} in {region} region")
    tags = get_lambda_tags(lambda_name_to_check, region)
    logger.debug(f"Tags for lambda {lambda_name_to_check} are: {tags}")
    lambda_version = tags.get(LAMBDA_VERSION_TAG, "")
    if not lambda_version:
        logger.error(f"Lambda {lambda_name_to_check} doesn't have tag {LAMBDA_VERSION_TAG}")
        return False, lambda_version
    logger.debug(f"Lambda {lambda_name_to_check} has tag {LAMBDA_VERSION_TAG} with value {lambda_version}")
    return True, lambda_version


def get_lambda_name_and_tag(svc_name, lambda_env_name, region) -> tuple[str, str]:
    """
    this function get svc nams and env name and try to get the lambda name and version tag
    this function will try to get the data via 2 options of lambda name according to the 2 conventions:
    1. {lambda_env_name}-{svc_name}
    2. {svc_name}-{lambda_env_name}
    :param svc_name:
    :param lambda_env_name:
    :param region:
    :return: tuple of lambda name and version tag
    """
    lambda_name = f"{lambda_env_name}-{svc_name}"
    is_valid_lambda_response, lambda_version_tag = check_if_lambda_exists_and_get_version_tag(lambda_name, region)
    if not is_valid_lambda_response:
        lambda_name = f"{svc_name}-{lambda_env_name}"
        is_valid_lambda_response, lambda_version_tag = check_if_lambda_exists_and_get_version_tag(lambda_name, region)
        if not is_valid_lambda_response:
            exit_on_error_and_write_summary(f"Lambda {lambda_name} doesn't have tag {LAMBDA_VERSION_TAG}")
    return lambda_name, lambda_version_tag
