"""
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 collections import OrderedDict
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,
    subnets: List = None,
    tags: List = 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, mandatory): A name, ID to identify the resource.
        db_subnet_group_description(TEXT, mandatory): DB Subnet Group description
        subnets(List, mandatory): The EC2 Subnet IDs for the DB subnet group
        tags:(List, optional): Tags to assign to the DB subnet group.

    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
    """

    result = dict(comment="", old_state=None, new_state=None, name=name, result=True)
    before = await hub.exec.boto3.client.rds.describe_db_subnet_groups(
        ctx, DBSubnetGroupName=name
    )
    old_db_subnet_group = {}
    is_updated = False
    is_tags_updated = False
    is_new = False
    db_subnet_group_arn = None
    old_tag_list = None
    if ctx.get("test", False):
        if before:
            result["comment"] = f"Would update aws.rds.db_subnet_group {name}"
            result["result"] = True
        else:
            result["comment"] = f"Would create aws.rds.db_subnet_group {name}"
            result["result"] = True
        return result
    if before:
        old_db_subnet_group = before["ret"]["DBSubnetGroups"][0]
        try:
            subnet_list = list()
            for each_subnet in old_db_subnet_group.get("Subnets"):
                subnet_list.append(each_subnet.get("SubnetIdentifier"))
            if set(subnets) != set(subnet_list):
                is_updated = True
            db_subnet_group_arn = old_db_subnet_group.get("DBSubnetGroupArn")
            ret_tag = await hub.exec.boto3.client.rds.list_tags_for_resource(
                ctx, ResourceName=db_subnet_group_arn
            )
            if ret_tag["result"]:
                old_tag_list = ret_tag.get("ret").get("TagList")
                old_db_subnet_group["tags"] = old_tag_list
            else:
                result["comment"] = ret_tag["comment"]
                result["result"] = False
                return result
            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"] = update_ret["comment"]
                    result["result"] = False
                    return result

            update_tags_ret = await hub.exec.aws.rds.tag.update_rds_tags(
                ctx=ctx,
                resource_arn=db_subnet_group_arn,
                old_tags=old_tag_list,
                new_tags=tags,
            )
            if not update_tags_ret["result"]:
                result["comment"] = update_tags_ret["comment"]
                result["result"] = False
                return result
            is_tags_updated = update_tags_ret["ret"]
            if is_updated or is_tags_updated:
                result["comment"] = f"Updated '{name}'"
            else:
                result["comment"] = f"'{name}' already exists"
        except Exception as e:
            result["comment"] = str(e)
            result["result"] = False
    else:
        try:
            ret = await hub.exec.boto3.client.rds.create_db_subnet_group(
                ctx,
                DBSubnetGroupName=name,
                DBSubnetGroupDescription=db_subnet_group_description,
                SubnetIds=subnets,
                Tags=tags,
            )
            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"] = f"Created '{name}'"
            is_new = True
        except hub.tool.boto3.exception.ClientError as e:
            result["comment"] = f"{e.__class__.__name__}: {e}"
            result["result"] = False
            return result

    try:
        if is_updated or is_new:
            after = await hub.exec.boto3.client.rds.describe_db_subnet_groups(
                ctx, DBSubnetGroupName=name
            )
            new_db_subnet_group = after["ret"]["DBSubnetGroups"][0]
        else:
            new_db_subnet_group = copy.deepcopy(old_db_subnet_group)
        if is_tags_updated or is_new:
            ret_tag = await hub.exec.boto3.client.rds.list_tags_for_resource(
                ctx, ResourceName=db_subnet_group_arn
            )
            new_tag_list = ret_tag.get("ret").get("TagList")
            new_db_subnet_group["tags"] = new_tag_list
        else:
            new_db_subnet_group["tags"] = old_tag_list

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


async def absent(hub, ctx, name: str) -> 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, mandatory): A name, ID 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)
    try:
        before = await hub.exec.boto3.client.rds.describe_db_subnet_groups(
            ctx, DBSubnetGroupName=name
        )
        if not before:
            result["comment"] = f"'{name}' already absent"
            return result
        elif ctx.get("test", False):
            result["comment"] = f"Would delete aws.rds.db_subnet_group {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"] = f"Deleted '{name}'"
            except hub.tool.boto3.exception.ClientError as e:
                result["comment"] = f"{e.__class__.__name__}: {e}"

        result["old_state"] = before["ret"]["DBSubnetGroups"][0]
    except Exception as e:
        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")
            describe_parameters = OrderedDict(
                {"DBSubnetGroupDescription": "db_subnet_group_description"}
            )
            new_db_subnet_group = []
            for parameter_old_key, parameter_new_key in describe_parameters.items():
                if db_subnet_group.get(parameter_old_key) is not None:
                    new_db_subnet_group.append(
                        {parameter_new_key: db_subnet_group.get(parameter_old_key)}
                    )

            if db_subnet_group.get("Subnets"):
                subnets = list()
                for each_subnet in db_subnet_group.get("Subnets"):
                    subnets.append(each_subnet.get("SubnetIdentifier"))

                new_db_subnet_group.append({"subnets": subnets})

            db_subnet_group_arn = db_subnet_group.get("DBSubnetGroupArn")
            ret_tag = await hub.exec.boto3.client.rds.list_tags_for_resource(
                ctx, ResourceName=db_subnet_group_arn
            )
            tag_list = ret_tag.get("ret").get("TagList")
            if tag_list:
                new_db_subnet_group.append({"tags": tag_list})
            result[db_subnet_group_id] = {
                "aws.rds.db_subnet_group.present": new_db_subnet_group
            }
    except Exception as e:
        result["comment"] = str(e)
        result["result"] = False
    return result
