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

hub.exec.boto3.client.elasticache.create_cache_subnet_group
hub.exec.boto3.client.elasticache.delete_cache_subnet_group
hub.exec.boto3.client.elasticache.describe_cache_subnet_groups
hub.exec.boto3.client.elasticache.modify_cache_subnet_group
"""
import copy
from typing import Any
from typing import Dict
from typing import List


__contracts__ = ["resource"]
TREQ = {
    "absent": {
        "require": [
            "aws.ec2.subnet.absent",
        ],
    },
    "present": {
        "require": [
            "aws.ec2.subnet.present",
        ],
    },
}


async def present(
    hub,
    ctx,
    name: str,
    subnet_ids: List,
    cache_subnet_group_description: str,
    resource_id: str = None,
    tags: List = None,
) -> Dict[str, Any]:
    r"""
    **Autogenerated function**

    Creates a new cache subnet group. Use cache subnet group parameter only when you are creating a cluster in an Amazon Virtual
    Private Cloud (Amazon VPC).

    Args:
        name(Text): An Idem name of the resource.
        cache_subnet_group_description(Text): Description of the cache subnet group
        subnet_ids(list): A list of VPC subnet IDs for the cache subnet group.
        resource_id(Text, optional): AWS Elasticache subnet group id to identify the resource
        tags(List, optional): A list of tags to be added to this resource.
            Key (string) - The key for the tag. May not be null.
            Value (string) - The tag's value. May be null.

    Request Syntax:
        [cache_subnet_group_name]:
          aws.elasticache.cache_subnet_group.present:
          - name: 'string'
          - cache_subnet_group_description: 'string'
          - subnet_ids: 'List'
          - tags:
            - Key: 'string'
              Value: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            cache_subnet_group_name:
              aws.elasticache.cache_subnet_group.present:
                - cache_subnet_group_description: "testing demo"
                - subnet_ids:
                    - subnet-239e4b44
                - tags:
                    - Key: Name
                      Value: test-elasticache
    """

    result = dict(comment="", name=name, old_state=None, new_state=None, result=True)
    before = None
    resource_updated = False
    if resource_id:
        before = await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(
            ctx, CacheSubnetGroupName=resource_id
        )
    try:
        if before and before["result"] and before["ret"]["CacheSubnetGroups"]:
            result[
                "old_state"
            ] = await hub.tool.aws.elasticache.conversion_utils.convert_raw_elasticache_subnet_to_present(
                ctx,
                raw_resource=before["ret"]["CacheSubnetGroups"][0],
                idem_resource_name=name,
            )
            plan_state = copy.deepcopy(result["old_state"])
            if cache_subnet_group_description != result["old_state"].get(
                "cache_subnet_group_description"
            ) or subnet_ids != result["old_state"].get(
                "cache_subnet_group_description"
            ):
                if not ctx.get("test", False):
                    update_ret = await hub.exec.boto3.client.elasticache.modify_cache_subnet_group(
                        ctx=ctx,
                        CacheSubnetGroupName=name,
                        CacheSubnetGroupDescription=cache_subnet_group_description,
                        SubnetIds=subnet_ids,
                    )
                    result["comment"] = update_ret["comment"]
                    result["result"] = update_ret["result"]
                    resource_updated = resource_updated or bool(update_ret["ret"])
                else:
                    if cache_subnet_group_description is not None:
                        plan_state[
                            "cache_subnet_group_description"
                        ] = cache_subnet_group_description
                    if subnet_ids is not None:
                        plan_state["subnet_ids"] = subnet_ids
            resource_arn = before["ret"]["CacheSubnetGroups"][0]["ARN"]
            if tags is not None and result["old_state"].get("tags") != tags:
                # Update tags
                update_ret = await hub.exec.aws.elasticache.tag.update_tags(
                    ctx=ctx,
                    resource_arn=resource_arn,
                    old_tags=result["old_state"].get("tags"),
                    new_tags=tags,
                )
                result["comment"] = f"{result['comment']} . {update_ret['comment']}"
                result["result"] = result["result"] and update_ret["result"]
                resource_updated = resource_updated or bool(update_ret["ret"])
                if ctx.get("test", False) and update_ret["ret"] is not None:
                    plan_state["tags"] = update_ret["ret"].get("tags")
        else:
            if ctx.get("test", False):
                result["new_state"] = hub.tool.aws.test_state_utils.generate_test_state(
                    enforced_state={},
                    desired_state={
                        "name": name,
                        "cache_subnet_group_description:": cache_subnet_group_description,
                        "subnet_ids": subnet_ids,
                        "tags": tags,
                    },
                )
                result[
                    "comment"
                ] = f"Would create aws.elasticache.cache_subnet_group {name}"
                return result
            ret = await hub.exec.boto3.client.elasticache.create_cache_subnet_group(
                ctx,
                CacheSubnetGroupName=name,
                CacheSubnetGroupDescription=cache_subnet_group_description,
                SubnetIds=subnet_ids,
                Tags=tags,
            )
            resource_id = name
            result["result"] = ret["result"]
            if not result["result"]:
                result["comment"] = ret["comment"]
                return result
            result["comment"] = f"Created '{name}'"
    except hub.tool.boto3.exception.ClientError as e:
        result["result"] = False
        result["comment"] = f"{e.__class__.__name__}: {e}"
    try:
        if ctx.get("test", False):
            result["new_state"] = plan_state
        elif (not before) or resource_updated:
            after = (
                await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(
                    ctx, CacheSubnetGroupName=resource_id
                )
            )
            result[
                "new_state"
            ] = await hub.tool.aws.elasticache.conversion_utils.convert_raw_elasticache_subnet_to_present(
                ctx,
                raw_resource=after["ret"]["CacheSubnetGroups"][0],
                idem_resource_name=name,
            )
        else:
            result["new_state"] = copy.deepcopy(result["old_state"])
    except Exception as e:
        result["comment"] = str(e)
        result["result"] = False
    return result


async def absent(hub, ctx, name: str, resource_id: str) -> Dict[str, Any]:
    r"""
    **Autogenerated function**

    Deletes a cache subnet group.  You cannot delete a default cache subnet group or one that is associated with any
    clusters.

    Args:
        name(Text): An Idem name of the resource.
        resource_id(Text): The AWS ID of the VPC

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            resource_is_absent:
              aws.elasticache.cache_subnet_group.absent:
                - name: value
    """

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

    before = await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(
        ctx, CacheSubnetGroupName=resource_id
    )
    if not before and not before["result"]:
        result["comment"] = f"'{name}' already absent"
        return result
    else:
        result[
            "old_state"
        ] = await hub.tool.aws.elasticache.conversion_utils.convert_raw_elasticache_subnet_to_present(
            ctx,
            raw_resource=before["ret"]["CacheSubnetGroups"][0],
            idem_resource_name=name,
        )
        if ctx.get("test", False):
            result[
                "comment"
            ] = f"Would delete aws.elasticache.cache_subnet_group {name}"
            return result
        try:
            ret = await hub.exec.boto3.client.elasticache.delete_cache_subnet_group(
                ctx, CacheSubnetGroupName=resource_id
            )
            result["result"] = ret["result"]
            if not result["result"]:
                result["comment"] = ret["comment"]
                return result
            result["comment"] = f"Deleted '{name}'"
        except hub.tool.boto3.exception.ClientError as e:
            result["comment"] = f"{e.__class__.__name__}: {e}"
    return result


async def describe(hub, ctx) -> Dict[str, Dict[str, Any]]:
    r"""
    **Autogenerated function**

    Describe the resource in a way that can be recreated/managed with the corresponding "present" function


    Returns a list of cache subnet group descriptions. If a subnet group name is specified, the list contains only
    the description of that group. This is applicable only when you have ElastiCache in VPC setup. All ElastiCache
    clusters now launch in VPC by default.


    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: bash

            $ idem describe aws.elasticache.cache_subnet_group
    """

    result = {}
    ret = await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(ctx)
    if not ret["result"]:
        hub.log.debug(f"Could not describe cache_subnet_group {ret['comment']}")
        return {}

    for resource in ret["ret"]["CacheSubnetGroups"]:
        resource_id = resource.get("CacheSubnetGroupName")
        resource_translated = await hub.tool.aws.elasticache.conversion_utils.convert_raw_elasticache_subnet_to_present(
            ctx, raw_resource=resource, idem_resource_name=resource_id
        )
        result[resource_id] = {
            "aws.elasticache.cache_subnet_group.present": [
                {parameter_key: parameter_value}
                for parameter_key, parameter_value in resource_translated.items()
            ]
        }
    return result
