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

hub.exec.boto3.client.ce.create_anomaly_monitor
hub.exec.boto3.client.ce.delete_anomaly_monitor
hub.exec.boto3.client.ce.get_anomaly_monitors
hub.exec.boto3.client.ce.update_anomaly_monitor
resource = hub.exec.boto3.client.ce.create_anomaly_monitor(ctx, AnomalyMonitor)
"""
import copy
from typing import Any
from typing import Dict

__contracts__ = ["resource"]


async def present(
    hub,
    ctx,
    name: str,
    monitor_name: str,
    monitor_type: str,
    monitor_dimension: str = None,
    monitor_specification: dict = None,
    resource_id: str = None,
) -> Dict[str, Any]:
    r"""
    **Autogenerated function**

    Creates a new cost anomaly detection monitor with the requested type and monitor specification.

    Args:
        name(Text): An Idem name of the resource.
        resource_id(Text): Monitor ARN to identify the resource.
        monitor_name: Name of anomaly monitor.
        monitor_type(Text): Possible type values. Valid Values: DIMENSIONAL | CUSTOM
        monitor_dimension(Text): The dimensions to evaluate : SERVICE
        monitor_specification(Dict, optional): Use Expression to filter by cost or by usage.
            Defaults to None.
            * And (list) -- Return results that match both Dimension objects.
            * Or (list) -- Return results that match either Dimension object.
            * Not (list) -- Return results that don't match a Dimension object.
            * Dimensions (dict) -- The specific Dimension to use for Expression.
                ** Key (string) -- The names of the metadata types that you can use to filter and group your results. For example, AZ returns a list of Availability Zones.
                ** Values (list) -- The metadata values that you can use to filter and group your results. You can use GetDimensionValues to find specific values.
                ** MatchOptions (list) -- The match options that you can use to filter your results. MatchOptions is only applicable for actions related to Cost Category. The default values for MatchOptions are EQUALS and CASE_SENSITIVE .
            * Tags (dict) -- The specific Tag to use for Expression.
                ** Key (string) -- The key for the tag.
                ** Values (list) -- The specific value of the tag.
                ** MatchOptions (list) -- The match options that you can use to filter your results. MatchOptions is only applicable for actions related to Cost Category. The default values for MatchOptions are EQUALS and CASE_SENSITIVE .
            * CostCategories (dict) -- The filter that's based on CostCategory values.
                ** Key (string) -- The unique name of the Cost Category.
                ** Values (list) -- The specific value of the Cost Category.
                ** MatchOptions (list) -- The match options that you can use to filter your results. MatchOptions is only applicable for actions related to cost category. The default values for MatchOptions is EQUALS and CASE_SENSITIVE .

    Request Syntax:
        [monitor-resource-id]:
          aws.costexplorer.anomaly_monitor.present:
          - resource_id: 'string'
          - monitor_name: 'string'
          - monitor_type: 'string'
          - monitor_specification:
            - Dimensions: 'dict'

    Returns:
        Dict[str, str]

    Examples:

        .. code-block:: sls

            cost_monitor1234:
              aws.costexplorer.anomaly_monitor.present:
              - name: cost_monitor1234
              - resource_id: cost_monitor1234
              - monitor_specification:
                Dimensions:
                  Key: LINKED_ACCOUNT
                  Values:
                    - '820272282974'
              - monitor_type: CUSTOM
    """
    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)
    before = None
    resource_updated = False

    if resource_id:
        before = await hub.exec.boto3.client.ce.get_anomaly_monitors(
            ctx, MonitorArnList=[resource_id]
        )

    if before and before["ret"].get("AnomalyMonitors"):
        before = before["ret"]["AnomalyMonitors"][0]
    else:
        before = None

    if not before:
        if ctx.get("test", False):
            result["new_state"] = hub.tool.aws.test_state_utils.generate_test_state(
                enforced_state={},
                desired_state={
                    "name": name,
                    "anomaly_monitor": {
                        "monitor_name": monitor_name,
                        "monitor_specification": monitor_specification,
                        "monitor_type": monitor_type,
                        "monitor_dimension": monitor_dimension,
                    },
                },
            )
            result["comment"] = (
                f"Would create aws.costexplorer.anomaly_monitor {name}",
            )
            return result

        monitor = None
        if monitor_specification:
            monitor = {
                "MonitorName": monitor_name,
                "MonitorSpecification": monitor_specification,
                "MonitorType": monitor_type,
            }
        else:
            monitor = {
                "MonitorName": monitor_name,
                "MonitorDimension": monitor_dimension,
                "MonitorType": monitor_type,
            }
        ret = await hub.exec.boto3.client.ce.create_anomaly_monitor(
            ctx,
            AnomalyMonitor=monitor,
        )
        result["result"] = ret["result"]
        if not result["result"]:
            result["comment"] = ret["comment"]
            return result
        result["comment"] = result["comment"] + (
            f"Created aws.costexplorer.anomaly_monitor '{name}'",
        )
        resource_id = ret["ret"]["MonitorArn"]
    else:

        result[
            "old_state"
        ] = hub.tool.aws.costexplorer.conversion_utils.convert_raw_monitor_to_present(
            ctx, raw_resource=before, idem_resource_name=name
        )
        plan_state = copy.deepcopy(result["old_state"])
        resource_id = before.get("MonitorArn")
        update_ret = await hub.exec.aws.costexplorer.anomaly_monitor.update_monitor(
            ctx, before=before, monitor_name=monitor_name, monitor_arn=resource_id
        )
        result["comment"] = result["comment"] + update_ret["comment"]
        result["result"] = update_ret["result"]
        resource_updated = resource_updated or bool(update_ret["ret"])
        if update_ret["ret"] and ctx.get("test", False):
            if "monitor_name" in update_ret["ret"]:
                plan_state["monitor_name"] = update_ret["ret"]["monitor_name"]

        if not resource_updated:
            result["comment"] = result["comment"] + (f"{name} already exists",)

    try:
        if ctx.get("test", False):
            result["new_state"] = plan_state
        elif (not before) or resource_updated:
            after = await hub.exec.boto3.client.ce.get_anomaly_monitors(
                ctx, MonitorArnList=[resource_id]
            )
            result[
                "new_state"
            ] = hub.tool.aws.costexplorer.conversion_utils.convert_raw_monitor_to_present(
                ctx,
                raw_resource=after["ret"]["AnomalyMonitors"][0],
                idem_resource_name=name,
            )
        else:
            result["new_state"] = copy.deepcopy(result["old_state"])
    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) -> Dict[str, Any]:
    r"""
    **Autogenerated function**

    Deletes a cost anomaly monitor by the specified monitor ARN as resource_id.

    Args:
        name(Text): The Idem name of the anomaly monitor.
        resource_id(Text): Monitor ARN to identify the resource.

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            cost_monitor1234:
              aws.costexplorer.anomaly_monitor.absent:
                - name: value
                - resource_id: cost_monitor1234
    """
    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)
    before = await hub.exec.boto3.client.ce.get_anomaly_monitors(
        ctx, MonitorArnList=[resource_id]
    )

    if before and before["ret"].get("AnomalyMonitors"):
        before = before["ret"]["AnomalyMonitors"][0]
    else:
        before = None

    if not before:
        result["comment"] = (
            f"aws.costexplorer.anomaly_monitor '{name}' already absent",
        )
    elif ctx.get("test", False):
        result[
            "old_state"
        ] = hub.tool.aws.costexplorer.conversion_utils.convert_raw_monitor_to_present(
            ctx, raw_resource=before, idem_resource_name=name
        )
        result["comment"] = (f"Would delete aws.costexplorer.anomaly_monitor {name}",)
        return result
    else:
        result[
            "old_state"
        ] = hub.tool.aws.costexplorer.conversion_utils.convert_raw_monitor_to_present(
            ctx, raw_resource=before, idem_resource_name=name
        )

        ret = await hub.exec.boto3.client.ce.delete_anomaly_monitor(
            ctx, MonitorArn=resource_id
        )
        result["result"] = ret["result"]
        if not result["result"]:
            result["comment"] = ret["comment"]
            return result
        result["comment"] = (f"Deleted aws.costexplorer.anomaly_monitor '{name}'",)

    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 aws cost anomaly monitors. If a monitor arn or name is specified, the list contains only
    the description of that monitor.


    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: bash

            $ idem describe aws.costexplorer.anomaly_monitor
    """
    result = {}
    ret = await hub.exec.boto3.client.ce.get_anomaly_monitors(ctx)

    if not ret["result"]:
        hub.log.debug(f"Could not describe cost anomaly monitors {ret['comment']}")
        return {}

    for monitor in ret["ret"]["AnomalyMonitors"]:
        resource_id = monitor.get("MonitorArn")
        resource_translated = (
            hub.tool.aws.costexplorer.conversion_utils.convert_raw_monitor_to_present(
                ctx, raw_resource=monitor, idem_resource_name=resource_id
            )
        )
        result[resource_id] = {
            "aws.costexplorer.anomaly_monitor.present": [
                {parameter_key: parameter_value}
                for parameter_key, parameter_value in resource_translated.items()
            ]
        }
    return result
