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


"""
from collections import OrderedDict
from typing import Any
from typing import Dict


__contracts__ = ["resource"]


async def present(
    hub,
    ctx,
    name: str,
    resource_group_name: str,
    account_name: str,
    parameters: dict = None,
    force_update: bool = False,
) -> dict:
    r"""
    **Autogenerated function**

    Create or update Storage Accounts

    Args:
        name(str): The identifier for this state.
        account_name(str): The name of the storage account within the specified resource group. Storage account names
         must be between 3 and 24 characters in length and use numbers and lower-case letters only.
        resource_group_name(str): The name of the resource group within the user's subscription. The name is case
         insensitive.Regex pattern: ^[-\w\._\(\)]+$.
        parameters(dict, optional): API request payload parameters. Defaults to {}.
        force_update(bool, optional): If PUT operation should be used instead of PATCH operation during resource update. Defaults to False.

    Returns:
        dict

    Examples:

        .. code-block:: sls

            resource_is_present:
              azure.storage_resource_provider.storage_accounts.present:
                - name: value
                - resource_group_name: value
                - account_name: value
    """
    ret = dict(name=name, old_state=None, new_state=None, result=True, comment="")
    if parameters is None:
        parameters = {}

    subscription_id = ctx.acct.subscription_id
    response_get = await hub.exec.request.json.get(
        ctx,
        url=f"{hub.exec.azure.URL}/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.Storage/storageAccounts/{account_name}?api-version=2021-04-01",
        success_codes=[200],
    )

    if force_update:
        if ctx.get("test", False):
            ret["comment"] = (
                "Would force to update azure.storage_resource_provider.storage_accounts",
            )
            return ret
        response_force_put = await hub.exec.request.json.put(
            ctx,
            url=f"{hub.exec.azure.URL}/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.Storage/storageAccounts/{account_name}?api-version=2021-04-01",
            success_codes=[200, 202],
            json=parameters,
        )
        if response_force_put["result"]:
            old_resource = response_get["ret"] if response_get["result"] else None
            ret["old_state"] = old_resource
            ret["new_state"] = response_force_put["ret"]
            ret["comment"] = response_force_put["comment"]
            return ret
        else:
            hub.log.debug(
                f"Could not force to update Storage Accounts {response_force_put['comment']} {response_force_put['ret']}"
            )
            ret["result"] = False
            ret["comment"] = response_force_put["comment"], response_force_put["ret"]
            return ret

    if not response_get["result"]:
        if ctx.get("test", False):
            ret["comment"] = (
                "Would create azure.storage_resource_provider.storage_accounts",
            )
            return ret

        if response_get["status"] == 404:
            # PUT operation to create a resource
            # For storage accounts, the PUT api is sent with raw function because the response value may not be in
            # json format, which will crash request.json.put
            response_put = await hub.exec.request.json.put(
                ctx,
                url=f"{hub.exec.azure.URL}/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.Storage/storageAccounts/{account_name}?api-version=2021-04-01",
                success_codes=[200, 202],
                json=parameters,
            )

            if not response_put["result"]:
                hub.log.debug(
                    f"Could not create Storage Accounts {response_put['comment']} {response_put['ret']}"
                )
                ret["result"] = False
                ret["comment"] = response_put["comment"], response_put["ret"]
                return ret

            # If the response is in bytes type and can be decoded, then we decode it to string
            response_put["ret"] = (
                response_put["ret"].decode()
                if hasattr(response_put["ret"], "decode")
                else response_put["ret"]
            )

            ret["new_state"] = response_put["ret"]
            ret["comment"] = response_put["comment"]
            return ret
        else:
            hub.log.debug(
                f"Could not get Storage Accounts {response_get['comment']} {response_get['ret']}"
            )
            ret["comment"] = response_get["comment"], response_get["ret"]
            return ret

    else:
        # PATCH operation to update a resource
        patch_parameters = {
            "identity": "identity",
            "kind": "kind",
            "properties": {
                "accessTier": "accessTier",
                "allowBlobPublicAccess": "allowBlobPublicAccess",
                "allowCrossTenantReplication": "allowCrossTenantReplication",
                "allowSharedKeyAccess": "allowSharedKeyAccess",
                "azureFilesIdentityBasedAuthentication": "azureFilesIdentityBasedAuthentication",
                "customDomain": "customDomain",
                "encryption": "encryption",
                "keyPolicy": "keyPolicy",
                "largeFileSharesState": "largeFileSharesState",
                "minimumTlsVersion": "minimumTlsVersion",
                "networkAcls": "networkAcls",
                "routingPreference": "routingPreference",
                "sasPolicy": "sasPolicy",
                "supportsHttpsTrafficOnly": "supportsHttpsTrafficOnly",
            },
            "sku": "sku",
            "tags": "tags",
        }
        existing_resource = response_get["ret"]
        new_parameters = hub.tool.azure.request.patch_json_content(
            patch_parameters, existing_resource, parameters
        )
        if ctx.get("test", False):
            ret["comment"] = (
                f"Would update azure.storage_resource_provider.storage_accounts with parameters: {new_parameters}",
            )
            return ret

        if not new_parameters:
            ret["old_state"] = existing_resource
            ret["new_state"] = existing_resource
            ret["comment"] = f"'{name}' has no property need to be updated."
            return ret

        response_patch = await hub.exec.request.json.patch(
            ctx,
            url=f"{hub.exec.azure.URL}/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.Storage/storageAccounts/{account_name}?api-version=2021-04-01",
            success_codes=[200],
            json=new_parameters,
        )

        if not response_patch["result"]:
            hub.log.debug(
                f"Could not update Storage Accounts {response_patch['comment']} {response_patch['ret']}"
            )
            return dict(
                name=name,
                result=False,
                comment=response_patch["comment"],
                error=response_patch["ret"],
            )

        ret["old_state"] = existing_resource
        ret["new_state"] = response_patch["ret"]
        ret["comment"] = response_patch["comment"]
    return ret


async def absent(
    hub, ctx, name: str, resource_group_name: str, account_name: str
) -> dict:
    r"""
    **Autogenerated function**

    Delete Storage Accounts

    Args:
        name(str): The identifier for this state.
        resource_group_name(str): The name of the resource group within the user's subscription. The name is case
         insensitive.Regex pattern: ^[-\w\._\(\)]+$.
        account_name(str): The name of the storage account within the specified resource group. Storage account
         names must be between 3 and 24 characters in length and use numbers and lower-case letters only.

    Returns:
        dict

    Examples:

        .. code-block:: sls

            resource_is_absent:
              azure.storage_resource_provider.storage_accounts.absent:
                - name: value
                - resource_group_name: value
                - account_name: value
    """

    subscription_id = ctx.acct.subscription_id
    response_get = await hub.exec.request.json.get(
        ctx,
        url=f"{hub.exec.azure.URL}/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.Storage/storageAccounts/{account_name}?api-version=2021-04-01",
        success_codes=[200],
    )
    if response_get["result"]:
        if ctx.get("test", False):
            return dict(
                name=name,
                result=True,
                comment="Would delete azure.storage_resource_provider.storage_accounts",
            )

        existing_resource = response_get["ret"]
        response_delete = await hub.exec.request.raw.delete(
            ctx,
            url=f"{hub.exec.azure.URL}/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.Storage/storageAccounts/{account_name}?api-version=2021-04-01",
            success_codes=[200, 204],
        )

        if not response_delete["result"]:
            hub.log.debug(
                f"Could not delete Storage Accounts {response_delete['comment']} {response_delete['ret']}"
            )
            return dict(
                name=name,
                result=False,
                comment=response_delete["comment"],
                error=response_delete["ret"],
            )

        return dict(
            name=name,
            result=True,
            old_state=existing_resource,
            new_state={},
            comment=response_delete["comment"],
        )
    elif response_get["status"] == 404:
        # If Azure returns 'Not Found' error, it means the resource has been absent.
        return dict(
            name=name,
            result=True,
            old_state=None,
            new_state=None,
            comment=f"'{name}' already absent",
        )
    else:
        hub.log.debug(
            f"Could not get Storage Accounts {response_get['comment']} {response_get['ret']}"
        )
        return dict(
            name=name,
            result=False,
            comment=response_get["comment"],
            error=response_get["ret"],
        )


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


    List all Storage Accounts under the same subscription


    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: bash

            $ idem describe azure.storage_resource_provider.storage_accounts
    """

    result = {}
    subscription_id = ctx.acct.subscription_id
    uri_parameters = OrderedDict(
        {"resourceGroups": "resource_group_name", "storageAccounts": "account_name"}
    )
    async for page_result in hub.tool.azure.request.paginate(
        ctx,
        url=f"{hub.exec.azure.URL}/subscriptions/{subscription_id}/providers/Microsoft.Storage/storageAccounts?api-version=2021-04-01",
        success_codes=[200],
    ):
        resource_list = page_result.get("value", None)
        if resource_list:
            for resource in resource_list:
                uri_parameter_values = hub.tool.azure.uri.get_parameter_value(
                    resource["id"], uri_parameters
                )
                result[resource["id"]] = {
                    f"azure.storage_resource_provider.storage_accounts.present": uri_parameter_values
                    + [{"parameters": resource}]
                }
    return result
