"""
Autogenerated using `pop-create-idem <https://gitlab.com/saltstack/pop/pop-create-idem>`__

hub.exec.boto3.client.apigatewayv2.create_stage
hub.exec.boto3.client.apigatewayv2.delete_stage
hub.exec.boto3.client.apigatewayv2.get_apis
hub.exec.boto3.client.apigatewayv2.get_stage
hub.exec.boto3.client.apigatewayv2.get_stages
hub.exec.boto3.client.apigatewayv2.tag_resource
hub.exec.boto3.client.apigatewayv2.untag_resource
hub.exec.boto3.client.apigatewayv2.update_stage
"""
import copy
from dataclasses import field
from dataclasses import make_dataclass
from typing import Any
from typing import Dict

__contracts__ = ["resource"]


async def present(
    hub,
    ctx,
    name: str,
    api_id: str,
    resource_id: str = None,
    access_log_settings: make_dataclass(
        "AccessLogSettings",
        [
            ("DestinationArn", str, field(default=None)),
            ("Format", str, field(default=None)),
        ],
    ) = None,
    auto_deploy: bool = None,
    client_certificate_id: str = None,
    default_route_settings: make_dataclass(
        "RouteSettings",
        [
            ("DataTraceEnabled", bool, field(default=None)),
            ("DetailedMetricsEnabled", bool, field(default=None)),
            ("LoggingLevel", str, field(default=None)),
            ("ThrottlingBurstLimit", int, field(default=None)),
            ("ThrottlingRateLimit", float, field(default=None)),
        ],
    ) = None,
    deployment_id: str = None,
    description: str = None,
    route_settings: Dict[
        str,
        make_dataclass(
            "RouteSettingsMap",
            [
                ("DataTraceEnabled", bool, field(default=None)),
                ("DetailedMetricsEnabled", bool, field(default=None)),
                ("LoggingLevel", str, field(default=None)),
                ("ThrottlingBurstLimit", int, field(default=None)),
                ("ThrottlingRateLimit", float, field(default=None)),
            ],
        ),
    ] = None,
    stage_variables: Dict[str, str] = None,
    tags: Dict = None,
) -> Dict[str, Any]:
    r"""
    Creates an API Gateway v2 stage resource.

    Args:
        name(string): An Idem name of the resource. This is also used as the name of the Stage during resource creation.
        api_id(string): The API resource identifier in Amazon Web Services.
        resource_id(string, optional): The stage resource name in Amazon Web Services.
        access_log_settings(Dict, optional): Settings for logging access in this stage. Defaults to None.
            * (DestinationArn, optional): The ARN of the CloudWatch Logs log group to receive access logs.
            * (Format, optional): A single line format of the access logs of data, as specified by selected $context variables.
                The format must include at least $context.requestId.
        auto_deploy(bool, optional): Specifies whether updates to an API automatically trigger a new deployment.
        client_certificate_id(string, optional): The identifier of a client certificate for a Stage. Supported only for WebSocket APIs.
        default_route_settings(Dict, optional): The default route settings for the stage. Defaults to None.
            * (DataTraceEnabled, optional): Specifies whether (true) or not (false) data trace logging is enabled for this route. This
                property affects the log entries pushed to Amazon CloudWatch Logs. Supported only for WebSocket
                APIs.
            * (DetailedMetricsEnabled, optional): Specifies whether detailed metrics are enabled.
            * (LoggingLevel, optional): Specifies the logging level for this route: INFO, ERROR, or OFF. This property affects the log
                entries pushed to Amazon CloudWatch Logs. Supported only for WebSocket APIs.
            * (ThrottlingBurstLimit, optional): Specifies the throttling burst limit.
            * (ThrottlingRateLimit, optional): Specifies the throttling rate limit.
        deployment_id(string, optional): The deployment identifier of the API stage.
        description(string, optional): The description for the API stage.
        route_settings(Dict[str, Dict], optional): Route settings for the stage, by routeKey. Defaults to None.
            * (DataTraceEnabled, optional): Specifies whether (true) or not (false) data trace logging is enabled for this route. This
                property affects the log entries pushed to Amazon CloudWatch Logs. Supported only for WebSocket
                APIs.
            * (DetailedMetricsEnabled, optional): Specifies whether detailed metrics are enabled.
            * (LoggingLevel, optional): Specifies the logging level for this route: INFO, ERROR, or OFF. This property affects the log
                entries pushed to Amazon CloudWatch Logs. Supported only for WebSocket APIs.
            * (ThrottlingBurstLimit, optional): Specifies the throttling burst limit.
            * (ThrottlingRateLimit, optional): Specifies the throttling rate limit.
        stage_variables(Dict, optional): A map that defines the stage variables for a Stage. Variable names can have alphanumeric and
            underscore characters, and the values must match [A-Za-z0-9-._~:/?#&=,]+.
        tags(Dict, optional): The collection of tags. Each tag element is associated with a given resource.

    Request Syntax:
        [idem_test_aws_apigatewayv2_stage]:
          aws.apigatewayv2.stage.present:
            - name: 'string'
            - api_id: 'string'
            - access_log_settings: {
                'DestinationArn': 'string',
                'Format': 'string'
              }
            - auto_deploy: True|False
            - client_certificate_id: 'string'
            - default_route_settings:{
                'DataTraceEnabled': True|False,
                'DetailedMetricsEnabled': True|False,
                'LoggingLevel': 'ERROR'|'INFO'|'OFF',
                'ThrottlingBurstLimit': int,
                'ThrottlingRateLimit': int
            }
            - deployment_id: 'string'
            - description: 'string'
            - route_settings: {
                'string': {
                    'DataTraceEnabled': True|False,
                    'DetailedMetricsEnabled': True|False,
                    'LoggingLevel': 'ERROR'|'INFO'|'OFF',
                    'ThrottlingBurstLimit': int,
                    'ThrottlingRateLimit': int
                }
              }
            - stage_variables: {'string': 'string'}
            - tags: {'string': 'string'}

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            idem_test_aws_apigatewayv2_stage:
              aws.apigatewayv2.stage.present:
                - name: value
                - api_id: value
                - access_log_settings: {}
                - auto_deploy: True|False
                - client_certificate_id: value
                - default_route_settings: {}
                - deployment_id: value
                - description: value
                - route_settings: {}
                - stage_variables: {}
                - tags: {}
    """

    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)

    before_ret = None
    resource_updated = False

    if resource_id:
        before_ret = await hub.exec.boto3.client.apigatewayv2.get_stage(
            ctx, ApiId=api_id, StageName=resource_id
        )
        if not before_ret["result"]:
            result["result"] = False
            result["comment"] = before_ret["comment"]
            return result

    if before_ret:
        result["comment"] = hub.tool.aws.comment_utils.already_exists_comment(
            resource_type="aws.apigatewayv2.stage", name=name
        )
        result[
            "old_state"
        ] = hub.tool.aws.apigatewayv2.stage.convert_raw_stage_to_present(
            api_id=api_id, raw_resource=before_ret.get("ret")
        )
        result["new_state"] = copy.deepcopy(result["old_state"])

        resource_parameters = {
            "AccessLogSettings": access_log_settings,
            "AutoDeploy": auto_deploy,
            "ClientCertificateId": client_certificate_id,
            "DefaultRouteSettings": default_route_settings,
            "DeploymentId": deployment_id,
            "Description": description,
            "RouteSettings": route_settings,
            "StageVariables": stage_variables,
        }

        update_stage_ret = await hub.exec.aws.apigatewayv2.stage.update(
            ctx,
            api_id=api_id,
            resource_id=resource_id,
            raw_resource=before_ret.get("ret"),
            resource_parameters=resource_parameters,
        )
        result["comment"] = result["comment"] + update_stage_ret["comment"]
        if not update_stage_ret["result"]:
            result["result"] = False
            return result

        resource_updated = resource_updated or bool(update_stage_ret["ret"])
        if update_stage_ret["ret"] and ctx.get("test", False):
            result["new_state"].update(update_stage_ret["ret"])

        if tags is not None and tags != result["old_state"].get("tags"):
            resource_arn = hub.tool.aws.arn_utils.build_arn(
                partition="aws",
                service="apigateway",
                region=ctx["acct"]["region_name"],
                resource="/apis/" + api_id + "/stages/" + resource_id,
            )
            update_tags_ret = await hub.exec.aws.apigatewayv2.tag.update_tags(
                ctx,
                resource_arn=resource_arn,
                old_tags=result["old_state"].get("tags", {}),
                new_tags=tags,
            )
            result["comment"] = result["comment"] + update_tags_ret["comment"]
            if not update_tags_ret["result"]:
                result["result"] = False
                return result

            resource_updated = resource_updated or bool(update_tags_ret["ret"])
            if update_tags_ret["ret"] and ctx.get("test", False):
                result["new_state"]["tags"] = update_tags_ret["ret"].get("tags")

        if resource_updated and ctx.get("test", False):
            return result
    else:
        if ctx.get("test", False):
            result[
                "new_state"
            ] = raw_resource = hub.tool.aws.test_state_utils.generate_test_state(
                enforced_state={},
                desired_state={
                    "name": name,
                    "api_id": api_id,
                    "access_log_settings": access_log_settings,
                    "auto_deploy": auto_deploy,
                    "client_certificate_id": client_certificate_id,
                    "default_route_settings": default_route_settings,
                    "deployment_id": deployment_id,
                    "description": description,
                    "route_settings": route_settings,
                    "stage_variables": stage_variables,
                    "tags": tags,
                },
            )
            result["comment"] = hub.tool.aws.comment_utils.would_create_comment(
                resource_type="aws.apigatewayv2.stage", name=name
            )
            return result

        create_ret = await hub.exec.boto3.client.apigatewayv2.create_stage(
            ctx,
            ApiId=api_id,
            AccessLogSettings=access_log_settings,
            AutoDeploy=auto_deploy,
            ClientCertificateId=client_certificate_id,
            DefaultRouteSettings=default_route_settings,
            DeploymentId=deployment_id,
            Description=description,
            RouteSettings=route_settings,
            StageName=name,
            StageVariables=stage_variables,
            Tags=tags,
        )
        if not create_ret["result"]:
            result["result"] = False
            result["comment"] = create_ret["comment"]
            return result

        result["comment"] = hub.tool.aws.comment_utils.create_comment(
            resource_type="aws.apigatewayv2.stage", name=name
        )
        resource_id = create_ret["ret"]["StageName"]

    if (not result["old_state"]) or resource_updated:
        after_ret = await hub.exec.boto3.client.apigatewayv2.get_stage(
            ctx, ApiId=api_id, StageName=resource_id
        )
        if not after_ret["result"]:
            result["result"] = False
            result["comment"] = result["comment"] + after_ret["comment"]
            return result

        result[
            "new_state"
        ] = hub.tool.aws.apigatewayv2.stage.convert_raw_stage_to_present(
            api_id=api_id, raw_resource=after_ret.get("ret")
        )

    return result


async def absent(
    hub, ctx, name: str, api_id: str, resource_id: str = None
) -> Dict[str, Any]:
    r"""
    Deletes an API Gateway v2 stage resource.

    Args:
        name(string): An Idem name of the resource.
        api_id(string): The API resource identifier in Amazon Web Services.
        resource_id(string, optional): The stage resource name in Amazon Web Services.
            Idem automatically considers this resource being absent if this field is not specified.

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            idem_test_aws_apigatewayv2_stage:
              aws.apigatewayv2.stage.absent:
                - name: value
                - api_id: value
                - resource_id: value
    """

    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)

    if not resource_id:
        result["comment"] = hub.tool.aws.comment_utils.already_absent_comment(
            resource_type="aws.apigatewayv2.stage", name=name
        )
        return result

    before_ret = await hub.exec.boto3.client.apigatewayv2.get_stage(
        ctx, ApiId=api_id, StageName=resource_id
    )
    if not before_ret["result"]:
        if "NotFoundException" not in str(before_ret["comment"][0]):
            result["result"] = False
            result["comment"] = before_ret["comment"]
        else:
            result["comment"] = hub.tool.aws.comment_utils.already_absent_comment(
                resource_type="aws.apigatewayv2.stage", name=name
            )
        return result

    result["old_state"] = hub.tool.aws.apigatewayv2.stage.convert_raw_stage_to_present(
        api_id=api_id, raw_resource=before_ret["ret"]
    )

    if ctx.get("test", False):
        result["comment"] = hub.tool.aws.comment_utils.would_delete_comment(
            resource_type="aws.apigatewayv2.stage", name=name
        )
        return result

    delete_ret = await hub.exec.boto3.client.apigatewayv2.delete_stage(
        ctx, ApiId=api_id, StageName=resource_id
    )
    if not delete_ret["result"]:
        result["result"] = False
        result["comment"] = delete_ret["comment"]
        return result

    result["comment"] = hub.tool.aws.comment_utils.delete_comment(
        resource_type="aws.apigatewayv2.stage", name=name
    )
    return result


async def describe(hub, ctx) -> Dict[str, Dict[str, Any]]:
    r"""
    Describe the resource in a way that can be recreated/managed with the corresponding "present" function

    Gets the API Gateway v2 stage resources for an AWS account.

    Returns:
        Dict[str, Dict[str, Any]]

    Examples:

        .. code-block:: bash

            $ idem describe aws.apigatewayv2.stage
    """

    result = {}

    get_apis_ret = await hub.exec.boto3.client.apigatewayv2.get_apis(ctx)
    if not get_apis_ret["result"]:
        hub.log.debug(f"Could not get apis {get_apis_ret['comment']}")
        return result

    for api in get_apis_ret["ret"]["Items"]:
        api_id = api.get("ApiId")

        get_stages_ret = await hub.exec.boto3.client.apigatewayv2.get_stages(
            ctx, ApiId=api_id
        )
        if not get_stages_ret["result"]:
            hub.log.debug(
                f"Could not get stages for ApiId '{api_id}': "
                f"{get_stages_ret['comment']}. Describe will skip this api and continue."
            )
            continue

        for stage in get_stages_ret["ret"]["Items"]:
            resource_translated = (
                hub.tool.aws.apigatewayv2.stage.convert_raw_stage_to_present(
                    api_id=api_id,
                    raw_resource=stage,
                )
            )

            result[resource_translated["resource_id"]] = {
                "aws.apigatewayv2.stage.present": [
                    {parameter_key: parameter_value}
                    for parameter_key, parameter_value in resource_translated.items()
                ]
            }

    return result


async def search(hub, ctx, name, api_id: str, resource_id: str) -> Dict[str, Any]:
    r"""
    Use an un-managed API Gateway v2 stage resource as a data-source.

    Args:
        name(string): An Idem name of the resource.
        api_id(string): The API resource identifier in Amazon Web Services.
        resource_id(string): The Stage resource name in Amazon Web Services.

    Request syntax:
        [idem_test_aws_apigatewayv2_stage]:
          aws.apigatewayv2.stage.search:
            - api_id: 'string'
            - resource_id: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            idem_test_aws_apigatewayv2_stage:
              aws.apigatewayv2.stage.search:
                - api_id: value
                - resource_id: value
    """

    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)

    search_ret = await hub.exec.boto3.client.apigatewayv2.get_stage(
        ctx, ApiId=api_id, StageName=resource_id
    )
    if not search_ret["result"]:
        result["result"] = False
        if "NotFoundException" not in str(search_ret["comment"][0]):
            result["comment"] = search_ret["result"]
        else:
            result["comment"] = (
                f"Unable to find aws.apigatewayv2.stage resource with resource id '{resource_id}'",
            )
        return result

    result["old_state"] = hub.tool.aws.apigatewayv2.stage.convert_raw_stage_to_present(
        api_id=api_id, raw_resource=search_ret["ret"]
    )
    result["new_state"] = copy.deepcopy(result["old_state"])

    return result
