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

hub.exec.boto3.client.rds.create_db_subnet_group
hub.exec.boto3.client.rds.delete_db_subnet_group
hub.exec.boto3.client.rds.describe_db_subnet_groups
hub.exec.boto3.client.rds.modify_db_subnet_group
"""
import copy
from typing import Any
from typing import Dict
from typing import List

__contracts__ = ["resource"]

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


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

    Creates a new DB subnet group. DB subnet groups must contain at least one subnet in at least two AZs in the
    Amazon Web Services Region.

    Args:
        name(Text): The Idem name of the DB subnet group.
        db_subnet_group_description(Text): DB Subnet Group description
        resource_id(Text, optional): AWS RDS DBSubnetGroupName to identify the resource
        subnets(List): The EC2 Subnet IDs for the DB subnet group
        tags(List or Dict, optional): Tags to assign to the DB subnet group. List of tags in the format of [{"Key": tag-key, "Value": tag-value}] or dict in the format of
                                      {tag-key: tag-value}

    Request Syntax:
        [db-subnet-group-name]:
          aws.rds.db_subnet_group.absent:
            - db_subnet_group_description: 'string'
            - subnets: 'list'
            - tags:
              - Key: 'string'
                Value: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            new-db-subnet-group:
                aws.rds.db_subnet_group.absent:
                  - db_subnet_group_description: "should not be blank"
                  - subnets:
                    - subnet-03e29c119d78899e1
                    - subnet-04dd5bc5aa08cbd89
                    - subnet-0754289517e31d331
                  - tags:
                    - Key: name
                      Value: new-db-subnet-group
    """

    plan_state = {}
    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)
    before = None
    if resource_id:
        before = await hub.exec.boto3.client.rds.describe_db_subnet_groups(
            ctx, DBSubnetGroupName=resource_id
        )
    tags = (
        hub.tool.aws.tag_utils.convert_tag_list_to_dict(tags)
        if isinstance(tags, List)
        else tags
    )
    old_db_subnet_group = {}
    is_updated = False
    are_tags_updated = False
    db_subnet_group_arn = None
    old_tag = None
    if before and before["result"]:
        try:
            subnet_list = []
            old_db_subnet_group = hub.tool.aws.rds.conversion_utils.convert_raw_db_subnet_group_to_present(
                resource=before["ret"]["DBSubnetGroups"][0],
                idem_resource_name=name,
            )
            for each_subnet in old_db_subnet_group.get("subnets"):
                subnet_list.append(each_subnet)
            if set(subnets) != set(subnet_list):
                is_updated = True
            db_subnet_group_arn = old_db_subnet_group.get("db_subnet_group_arn")
            ret_tag = await hub.exec.boto3.client.rds.list_tags_for_resource(
                ctx, ResourceName=db_subnet_group_arn
            )
            if ret_tag["result"]:
                old_tag = hub.tool.aws.tag_utils.convert_tag_list_to_dict(
                    ret_tag.get("ret").get("TagList")
                )
                old_db_subnet_group["tags"] = old_tag
            else:
                result["comment"] = ret_tag["comment"]
                result["result"] = False
                return result
            plan_state = copy.deepcopy(old_db_subnet_group)
            if ctx.get("test", False):
                plan_state["subnets"] = subnets
                plan_state["subnets"].sort()
                if db_subnet_group_description:
                    plan_state[
                        "db_subnet_group_description"
                    ] = db_subnet_group_description
            else:
                if is_updated:
                    update_ret = await hub.exec.boto3.client.rds.modify_db_subnet_group(
                        ctx,
                        DBSubnetGroupName=name,
                        DBSubnetGroupDescription=db_subnet_group_description,
                        SubnetIds=subnets,
                    )
                    if not update_ret["result"]:
                        result["comment"] = result["comment"] + update_ret["comment"]
                        result["result"] = False
                        return result
            if tags is not None and tags != old_tag:
                update_tags_ret = await hub.exec.aws.rds.tag.update_rds_tags(
                    ctx=ctx,
                    resource_arn=db_subnet_group_arn,
                    old_tags=old_tag,
                    new_tags=tags,
                )
                if not update_tags_ret["result"]:
                    result["comment"] = result["comment"] + update_tags_ret["comment"]
                    result["result"] = False
                    return result
                are_tags_updated = update_tags_ret["result"]
            if ctx.get("test", False):
                if are_tags_updated:
                    plan_state["tags"] = update_tags_ret["ret"]
            elif is_updated or are_tags_updated:
                result["comment"] = result["comment"] + (f"Updated '{name}'",)
            else:
                result["comment"] = result["comment"] + (f"'{name}' already exists",)
        except Exception as e:
            result["comment"] = result["comment"] + (str(e),)
            result["result"] = False
    else:
        if ctx.get("test", False):
            result["new_state"] = hub.tool.aws.test_state_utils.generate_test_state(
                enforced_state={},
                desired_state={
                    "name": name,
                    "db_subnet_group_description": db_subnet_group_description,
                    "resource_id": resource_id,
                    "subnets": subnets,
                    "tags": tags,
                },
            )
            result["comment"] = hub.tool.aws.comment_utils.would_create_comment(
                resource_type="aws.rds.db_subnet_group", name=name
            )
            return result
        try:
            ret = await hub.exec.boto3.client.rds.create_db_subnet_group(
                ctx,
                DBSubnetGroupName=name,
                DBSubnetGroupDescription=db_subnet_group_description,
                SubnetIds=subnets,
                Tags=hub.tool.aws.tag_utils.convert_tag_dict_to_list(tags)
                if tags
                else None,
            )
            result["result"] = ret["result"]
            if not result["result"]:
                result["comment"] = ret["comment"]
                return result
            db_subnet_group_arn = (
                ret["ret"].get("DBSubnetGroup").get("DBSubnetGroupArn")
            )
            result["comment"] = result[
                "comment"
            ] + hub.tool.aws.comment_utils.create_comment(
                resource_type="aws.rds.db_subnet_group", name=name
            )
        except hub.tool.boto3.exception.ClientError as e:
            result["comment"] = result["comment"] + (f"{e.__class__.__name__}: {e}",)
            result["result"] = False
            return result

    try:
        if ctx.get("test", False):
            new_db_subnet_group = plan_state
        elif is_updated or not (before and before["result"]):
            after = await hub.exec.boto3.client.rds.describe_db_subnet_groups(
                ctx, DBSubnetGroupName=name
            )
            new_db_subnet_group = hub.tool.aws.rds.conversion_utils.convert_raw_db_subnet_group_to_present(
                resource=after["ret"]["DBSubnetGroups"][0],
                idem_resource_name=name,
            )
        else:
            new_db_subnet_group = copy.deepcopy(old_db_subnet_group)

        if not ctx.get("test", False):
            if are_tags_updated or not (before and before["result"]):
                ret_tag = await hub.exec.boto3.client.rds.list_tags_for_resource(
                    ctx, ResourceName=db_subnet_group_arn
                )
                new_db_subnet_group[
                    "tags"
                ] = hub.tool.aws.tag_utils.convert_tag_list_to_dict(
                    ret_tag.get("ret").get("TagList")
                )
            else:
                new_db_subnet_group["tags"] = old_tag

        result["old_state"] = old_db_subnet_group
        result["new_state"] = new_db_subnet_group
    except Exception as e:
        result["comment"] = result["comment"] + (str(e),)
        result["result"] = False
    return result


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

    Deletes a DB subnet group.  The specified database subnet group must not be associated with any DB instances.

    Args:
        name(Text): The Idem name of the DB subnet group.
        resource_id(Text, optional): The AWS RDS DBSubnetGroupName to identify the resource

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            resource_is_absent:
              aws.rds.db_subnet_group.absent:
                - name: 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.rds.db_subnet_group", name=name
        )
        return result
    try:
        before = await hub.exec.boto3.client.rds.describe_db_subnet_groups(
            ctx, DBSubnetGroupName=resource_id
        )
        if not before:
            result["comment"] = result[
                "comment"
            ] = hub.tool.aws.comment_utils.already_absent_comment(
                resource_type="aws.rds.db_subnet_group", name=name
            )
            return result
        else:
            tags = await hub.exec.boto3.client.rds.list_tags_for_resource(
                ctx,
                ResourceName=(before["ret"]["DBSubnetGroups"][0]).get(
                    "DBSubnetGroupArn"
                ),
            )
            result[
                "old_state"
            ] = hub.tool.aws.rds.conversion_utils.convert_raw_db_subnet_group_to_present(
                resource=before["ret"]["DBSubnetGroups"][0],
                tags=hub.tool.aws.tag_utils.convert_tag_list_to_dict(
                    tags.get("ret").get("TagList")
                )
                if tags.get("result")
                else None,
                idem_resource_name=name,
            )
            if ctx.get("test", False):
                result["comment"] = hub.tool.aws.comment_utils.would_delete_comment(
                    resource_type="aws.rds.db_subnet_group", name=name
                )
                return result
            else:
                try:
                    ret = await hub.exec.boto3.client.rds.delete_db_subnet_group(
                        ctx, DBSubnetGroupName=name
                    )
                    result["result"] = ret["result"]
                    if not result["result"]:
                        result["comment"] = ret["comment"]
                        result["result"] = False
                        return result
                    result["comment"] = hub.tool.aws.comment_utils.delete_comment(
                        resource_type="aws.rds.db_subnet_group", name=name
                    )
                except hub.tool.boto3.exception.ClientError as e:
                    result["comment"] = (f"{e.__class__.__name__}: {e}",)
                    result["result"] = False
    except Exception as e:
        result["comment"] = result["comment"] + (str(e),)
        result["result"] = False
    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 DBSubnetGroup descriptions. For an overview of CIDR ranges, go to the Wikipedia Tutorial.


    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: bash

            $ idem describe aws.rds.db_subnet_group
    """

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

        for db_subnet_group in ret["ret"]["DBSubnetGroups"]:
            db_subnet_group_id = db_subnet_group.get("DBSubnetGroupName")
            tags = None
            ret_tags = await hub.exec.boto3.client.rds.list_tags_for_resource(
                ctx, ResourceName=db_subnet_group.get("DBSubnetGroupArn")
            )
            if not ret_tags:
                result["comment"] = ret_tags["comment"]
                result["result"] = False
            else:
                tags = hub.tool.aws.tag_utils.convert_tag_list_to_dict(
                    ret_tags.get("ret").get("TagList")
                )
            resource_converted = hub.tool.aws.rds.conversion_utils.convert_raw_db_subnet_group_to_present(
                resource=db_subnet_group,
                tags=tags,
                idem_resource_name=db_subnet_group_id,
            )
            result[db_subnet_group_id] = {
                "aws.rds.db_subnet_group.present": [resource_converted]
            }
    except Exception as e:
        result["comment"] = str(e)
        result["result"] = False
    return result
