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

hub.exec.boto3.client.apigatewayv2.create_route
hub.exec.boto3.client.apigatewayv2.delete_route
hub.exec.boto3.client.apigatewayv2.get_apis
hub.exec.boto3.client.apigatewayv2.get_route
hub.exec.boto3.client.apigatewayv2.get_routes
hub.exec.boto3.client.apigatewayv2.tag_resource
hub.exec.boto3.client.apigatewayv2.untag_resource
hub.exec.boto3.client.apigatewayv2.update_route
"""
import copy
from dataclasses import field
from dataclasses import make_dataclass
from typing import Any
from typing import Dict
from typing import List

__contracts__ = ["resource"]


async def present(
    hub,
    ctx,
    name: str,
    api_id: str,
    route_key: str,
    resource_id: str = None,
    api_key_required: bool = None,
    authorization_scopes: List[str] = None,
    authorization_type: str = None,
    authorizer_id: str = None,
    model_selection_expression: str = None,
    operation_name: str = None,
    request_models: Dict = None,
    request_parameters: Dict[
        str,
        make_dataclass("RouteParameters", [("Required", bool, field(default=None))]),
    ] = None,
    route_response_selection_expression: str = None,
    target: str = None,
) -> Dict[str, Any]:
    r"""
    Creates an API Gateway v2 route resource.

    Args:
        name(string): An Idem name of the resource.
        api_id(string): The API resource identifier in Amazon Web Services.
        route_key(string): The route key for the route.
        resource_id(string, optional): The route resource identifier in Amazon Web Services.
        api_key_required(bool, optional): Specifies whether an API key is required for the route. Supported only for WebSocket APIs.
        authorization_scopes(List, optional): The authorization scopes supported by this route.
        authorization_type(string, optional): The authorization type for the route. For WebSocket APIs, valid values are NONE for open access,
            AWS_IAM for using AWS IAM permissions, and CUSTOM for using a Lambda authorizer For HTTP APIs,
            valid values are NONE for open access, JWT for using JSON Web Tokens, AWS_IAM for using AWS IAM
            permissions, and CUSTOM for using a Lambda authorizer.
        authorizer_id(string, optional): The identifier of the Authorizer resource to be associated with this route. The authorizer
            identifier is generated by API Gateway when you created the authorizer.
        model_selection_expression(string, optional): The model selection expression for the route. Supported only for WebSocket APIs.
        operation_name(string, optional): The operation name for the route.
        request_models(Dict, optional): The request models for the route. Supported only for WebSocket APIs.
        request_parameters(Dict[str, Dict], optional): The request parameters for the route. Supported only for WebSocket APIs. Defaults to None.
            * (Required, optional): Whether or not the parameter is required.
        route_response_selection_expression(string, optional): The route response selection expression for the route. Supported only for WebSocket APIs.
        target(string, optional): The target for the route.

    Request Syntax:
        [idem_test_aws_apigatewayv2_route]:
          aws.apigatewayv2.route.present:
            - name: 'string'
            - api_id: 'string'
            - route_key: 'string'
            - api_key_required: True|False
            - authorization_scopes: ['string']
            - authorization_type: 'NONE'|'AWS_IAM'|'CUSTOM'|'JWT'
            - authorizer_id: 'string'
            - model_selection_expression: 'string'
            - operation_name: 'string'
            - request_models: {'string': 'string'}
            - request_parameters: {
                'string': {
                    'Required': True|False
                }
              }
            - route_response_selection_expression: 'string'
            - target: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            idem_test_aws_apigatewayv2_route:
              aws.apigatewayv2.route.present:
                - name: value
                - api_id: value
                - route_key: value
                - api_key_required: True|False
                - authorization_scopes: []
                - authorization_type: value
                - authorizer_id: value
                - model_selection_expression: value
                - operation_name: value
                - request_models: {}
                - request_parameters: {}
                - route_response_selection_expression: value
                - target: value
    """

    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_route(
            ctx, ApiId=api_id, RouteId=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.route", name=name
        )
        result[
            "old_state"
        ] = hub.tool.aws.apigatewayv2.route.convert_raw_route_to_present(
            api_id=api_id, raw_resource=before_ret.get("ret"), idem_resource_name=name
        )
        result["new_state"] = copy.deepcopy(result["old_state"])

        resource_parameters = {
            "ApiKeyRequired": api_key_required,
            "AuthorizationScopes": authorization_scopes,
            "AuthorizationType": authorization_type,
            "AuthorizerId": authorizer_id,
            "ModelSelectionExpression": model_selection_expression,
            "OperationName": operation_name,
            "RequestModels": request_models,
            "RequestParameters": request_parameters,
            "RouteKey": route_key,
            "RouteResponseSelectionExpression": route_response_selection_expression,
            "Target": target,
        }

        update_route_ret = await hub.exec.aws.apigatewayv2.route.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_route_ret["comment"]
        if not update_route_ret["result"]:
            result["result"] = False
            return result

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

        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,
                    "api_key_required": api_key_required,
                    "authorization_scopes": authorization_scopes,
                    "authorization_type": authorization_type,
                    "authorizer_id": authorizer_id,
                    "model_selection_expression": model_selection_expression,
                    "operation_name": operation_name,
                    "request_models": request_models,
                    "request_parameters": request_parameters,
                    "route_key": route_key,
                    "route_response_selection_expression": route_response_selection_expression,
                    "target": target,
                },
            )
            result["comment"] = hub.tool.aws.comment_utils.would_create_comment(
                resource_type="aws.apigatewayv2.route", name=name
            )
            return result

        create_ret = await hub.exec.boto3.client.apigatewayv2.create_route(
            ctx,
            ApiId=api_id,
            ApiKeyRequired=api_key_required,
            AuthorizationScopes=authorization_scopes,
            AuthorizationType=authorization_type,
            AuthorizerId=authorizer_id,
            ModelSelectionExpression=model_selection_expression,
            OperationName=operation_name,
            RequestModels=request_models,
            RequestParameters=request_parameters,
            RouteKey=route_key,
            RouteResponseSelectionExpression=route_response_selection_expression,
            Target=target,
        )
        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.route", name=name
        )
        resource_id = create_ret["ret"]["RouteId"]

    if (not result["old_state"]) or resource_updated:
        after_ret = await hub.exec.boto3.client.apigatewayv2.get_route(
            ctx, ApiId=api_id, RouteId=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.route.convert_raw_route_to_present(
            api_id=api_id, raw_resource=after_ret.get("ret"), idem_resource_name=name
        )

    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 route 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 Route resource identifier 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_route:
              aws.apigatewayv2.route.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.route", name=name
        )
        return result

    before_ret = await hub.exec.boto3.client.apigatewayv2.get_route(
        ctx, ApiId=api_id, RouteId=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.route", name=name
            )
        return result

    result["old_state"] = hub.tool.aws.apigatewayv2.route.convert_raw_route_to_present(
        api_id=api_id, raw_resource=before_ret["ret"], idem_resource_name=name
    )

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

    delete_ret = await hub.exec.boto3.client.apigatewayv2.delete_route(
        ctx, ApiId=api_id, RouteId=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.route", 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 route resources for an AWS account.

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

    Examples:

        .. code-block:: bash

            $ idem describe aws.apigatewayv2.route
    """

    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_routes_ret = await hub.exec.boto3.client.apigatewayv2.get_routes(
            ctx, ApiId=api_id
        )
        if not get_routes_ret["result"]:
            hub.log.debug(
                f"Could not get routes for ApiId '{api_id}': "
                f"{get_routes_ret['comment']}. Describe will skip this api and continue."
            )
            continue

        for route in get_routes_ret["ret"]["Items"]:
            resource_translated = (
                hub.tool.aws.apigatewayv2.route.convert_raw_route_to_present(
                    api_id=api_id,
                    raw_resource=route,
                )
            )

            result[resource_translated["name"]] = {
                "aws.apigatewayv2.route.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 route 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 Route resource identifier in Amazon Web Services.

    Request syntax:
        [idem_test_aws_apigatewayv2_route]:
          aws.apigatewayv2.route.search:
            - api_id: 'string'
            - resource_id: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            idem_test_aws_apigatewayv2_route:
              aws.apigatewayv2.route.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_route(
        ctx, ApiId=api_id, RouteId=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.route resource with resource id '{resource_id}'",
            )
        return result

    result["old_state"] = hub.tool.aws.apigatewayv2.route.convert_raw_route_to_present(
        api_id=api_id, raw_resource=search_ret["ret"], idem_resource_name=name
    )
    result["new_state"] = copy.deepcopy(result["old_state"])

    return result
