# This file is automatically generated by botocraft.  Do not edit directly.
# mypy: disable-error-code="index, override, assignment, union-attr, misc"
from botocraft.mixins.tags import TagsDictMixin
from .abstract import PrimaryBoto3ModelQuerySet
from typing import ClassVar, Type, Optional, Literal, Dict, List, Union, Any, cast
from datetime import datetime
from botocraft.services.common import Tag
from pydantic import Field
from .abstract import (
    Boto3Model,
    ReadonlyBoto3Model,
    PrimaryBoto3Model,
    ReadonlyPrimaryBoto3Model,
    Boto3ModelManager,
    ReadonlyBoto3ModelManager,
)
from botocraft.mixins.kms import kms_keys_only

# ===============
# Managers
# ===============


class KMSKeyManager(Boto3ModelManager):
    service_name: str = "kms"

    def create(
        self,
        model: "KMSKey",
        Policy: str | None = None,
        BypassPolicyLockoutSafetyCheck: bool | None = None,
        Tags: List[Tag] | None = None,
        XksKeyId: str | None = None,
    ) -> "KMSKey":
        """
        Creates a unique customer managed `KMS key <https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms-
        keys>`_ in your Amazon Web Services account and Region. You can use a KMS key in cryptographic operations, such as
        encryption and signing. Some Amazon Web Services services let you use KMS keys that you create and manage to protect
        your service resources.

        Args:
            model: The :py:class:`KeyMetadata` to create.

        Keyword Args:
            Policy: The key policy to attach to the KMS key.
            BypassPolicyLockoutSafetyCheck: Skips ("bypasses") the key policy lockout safety check. The default value is false.
            Tags: Assigns one or more tags to the KMS key. Use this parameter to tag the KMS key when it is created. To tag an
                existing KMS key, use the TagResource operation.
            XksKeyId: Identifies the `external key <https://docs.aws.amazon.com/kms/latest/developerguide/keystore-
                external.html#concept- external-key>`_ that serves as key material for the KMS key in an `external key store
                <https://docs.aws.amazon.com/kms/latest/developerguide/keystore-external.html>`_. Specify the ID that the `external
                key store proxy <https://docs.aws.amazon.com/kms/latest/developerguide/keystore-external.html#concept-xks-proxy>`_
                uses to refer to the external key. For help, see the documentation for your external key store proxy.

        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            Policy=self.serialize(Policy),
            Description=data.get("Description"),
            KeyUsage=data.get("KeyUsage"),
            CustomerMasterKeySpec=data.get("CustomerMasterKeySpec"),
            KeySpec=data.get("KeySpec"),
            Origin=data.get("Origin"),
            CustomKeyStoreId=data.get("CustomKeyStoreId"),
            BypassPolicyLockoutSafetyCheck=self.serialize(
                BypassPolicyLockoutSafetyCheck
            ),
            Tags=self.serialize(Tags),
            MultiRegion=data.get("MultiRegion"),
            XksKeyId=self.serialize(XksKeyId),
        )
        _response = self.client.create_key(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CreateKeyResponse(**_response)

        self.sessionize(response.KeyMetadata)
        return cast("KMSKey", response.KeyMetadata)

    def get(
        self, KeyId: str, *, GrantTokens: List[str] | None = None
    ) -> Optional["KMSKey"]:
        """
        Provides detailed information about a KMS key. You can run ``DescribeKey`` on a `customer managed
        key <https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-mgn-key>`_ or an `Amazon Web Services
        managed key <https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-key>`_.

        Args:
            KeyId: Describes the specified KMS key.

        Keyword Args:
            GrantTokens: A list of grant tokens.

        """
        args: Dict[str, Any] = dict(
            KeyId=self.serialize(KeyId), GrantTokens=self.serialize(GrantTokens)
        )
        _response = self.client.describe_key(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = DescribeKeyResponse(**_response)

        if response and response.KeyMetadata:
            self.sessionize(response.KeyMetadata)
            return response.KeyMetadata
        return None

    @kms_keys_only
    def list(self, *, Limit: int | None = None) -> PrimaryBoto3ModelQuerySet:
        """
        Gets a list of all KMS keys in the caller's Amazon Web Services account and
        Region.

        Keyword Args:
            Limit: Use this parameter to specify the maximum number of items to return. When this value is present, KMS does not
                return more than the specified number of items, but it might return fewer.
        """
        paginator = self.client.get_paginator("list_keys")
        args: Dict[str, Any] = dict(Limit=self.serialize(Limit))
        response_iterator = paginator.paginate(
            **{k: v for k, v in args.items() if v is not None}
        )
        results = []
        for _response in response_iterator:
            if list(_response.keys()) == ["ResponseMetadata"]:
                break
            if "ResponseMetadata" in _response:
                del _response["ResponseMetadata"]
            response = ListKeysResponse(**_response)
            if response.Keys:
                results.extend(response.Keys)
            else:
                if getattr(response, "NextToken", None):
                    continue
                break
        self.sessionize(results)
        if results and isinstance(results[0], Boto3Model):
            return PrimaryBoto3ModelQuerySet(results)
        return results

    def delete(
        self, KeyId: str, *, PendingWindowInDays: int = 7
    ) -> "ScheduleKeyDeletionResponse":
        """
        Schedules the deletion of a KMS key. By default, KMS applies a waiting period of
        30 days, but you can specify a waiting period of 7-30 days. When this operation
        is successful, the key state of the KMS key changes to ``PendingDeletion`` and
        the key can't be used in any cryptographic operations. It remains in this state
        for the duration of the waiting period. Before the waiting period ends, you can
        use CancelKeyDeletion to cancel the deletion of the KMS key. After the waiting
        period ends, KMS deletes the KMS key, its key material, and all KMS data
        associated with it, including all aliases that refer to it.

        Args:
            KeyId: The unique identifier of the KMS key to delete.

        Keyword Args:
            PendingWindowInDays: The waiting period, specified in number of days. After the waiting period ends, KMS deletes the
                KMS key.
        """
        args: Dict[str, Any] = dict(
            KeyId=self.serialize(KeyId),
            PendingWindowInDays=self.serialize(PendingWindowInDays),
        )
        _response = self.client.schedule_key_deletion(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = ScheduleKeyDeletionResponse(**_response)
        return response

    def enable(self, KeyId: str) -> None:
        """
        Sets the key state of a KMS key to enabled. This allows you to use the KMS key for `cryptographic
        operations <https://docs.aws.amazon.com/kms/latest/developerguide/kms-cryptography.html#cryptographic-operations>`_.

        Args:
            KeyId: Identifies the KMS key to enable.

        """
        args: Dict[str, Any] = dict(KeyId=self.serialize(KeyId))
        self.client.enable_key(**{k: v for k, v in args.items() if v is not None})

    def disable(self, KeyId: str) -> None:
        """
        Sets the state of a KMS key to disabled. This change temporarily prevents use of the KMS key for `cryptographic
        operations <https://docs.aws.amazon.com/kms/latest/developerguide/kms-cryptography.html#cryptographic-operations>`_.

        Args:
            KeyId: Identifies the KMS key to disable.

        """
        args: Dict[str, Any] = dict(KeyId=self.serialize(KeyId))
        self.client.disable_key(**{k: v for k, v in args.items() if v is not None})

    def cancel_deletion(self, KeyId: str) -> str:
        """
        Cancels the deletion of a KMS key. When this operation succeeds, the key state
        of the KMS key is ``Disabled``. To enable the KMS key, use EnableKey.

        Args:
            KeyId: Identifies the KMS key whose deletion is being canceled.
        """
        args: Dict[str, Any] = dict(KeyId=self.serialize(KeyId))
        _response = self.client.cancel_key_deletion(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CancelKeyDeletionResponse(**_response)

        results: str = None
        if response is not None:
            results = response.KeyId

        self.sessionize(results)
        return cast("str", results)

    def create_alias(self, AliasName: str, TargetKeyId: str) -> "None":
        """
        Creates a friendly name for a KMS key.

        Args:
            AliasName: Specifies the alias name. This value must begin with ``alias/`` followed by a name, such as
                ``alias/ExampleAlias``.
            TargetKeyId: Associates the alias with the specified `customer managed key
                <https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-mgn-key>`_. The KMS key must be in the
                same Amazon Web Services Region.
        """
        args: Dict[str, Any] = dict(
            AliasName=self.serialize(AliasName), TargetKeyId=self.serialize(TargetKeyId)
        )
        self.client.create_alias(**{k: v for k, v in args.items() if v is not None})

    def update_alias(self, AliasName: str, TargetKeyId: str) -> "None":
        """
        Associates an existing KMS alias with a different KMS key. Each alias is
        associated with only one KMS key at a time, although a KMS key can have multiple
        aliases. The alias and the KMS key must be in the same Amazon Web Services
        account and Region.

        Args:
            AliasName: Identifies the alias that is changing its KMS key. This value must begin with ``alias/`` followed by the
                alias name, such as ``alias/ExampleAlias``. You cannot use ``UpdateAlias`` to change the alias name.
            TargetKeyId: Identifies the `customer managed key
                <https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-mgn- key>`_ to associate with the
                alias. You don't have permission to associate an alias with an `Amazon Web Services managed key
                <https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-key>`_.
        """
        args: Dict[str, Any] = dict(
            AliasName=self.serialize(AliasName), TargetKeyId=self.serialize(TargetKeyId)
        )
        self.client.update_alias(**{k: v for k, v in args.items() if v is not None})


# ==============
# Service Models
# ==============


class MultiRegionKey(Boto3Model):
    """
    Describes the primary or replica key in a multi-Region key.
    """

    Arn: str | None = None
    """
    Displays the key ARN of a primary or replica key of a multi-Region key.
    """
    Region: str | None = None
    """
    Displays the Amazon Web Services Region of a primary or replica key in a multi-
    Region key.
    """


class KMSMultiRegionConfiguration(Boto3Model):
    """
    Describes the configuration of this multi-Region key. This field appears only when
    the KMS key is a primary or replica of a multi-Region key.

    For more information about any listed KMS key, use the DescribeKey operation.
    """

    MultiRegionKeyType: Literal["PRIMARY", "REPLICA"] | None = None
    """
    Indicates whether the KMS key is a ``PRIMARY`` or ``REPLICA`` key.
    """
    PrimaryKey: MultiRegionKey | None = None
    """
    Displays the key ARN and Region of the primary key.

    This field includes the current KMS key if it is the primary key.
    """
    ReplicaKeys: List["MultiRegionKey"] | None = None
    """
    Displays the key ARNs and Regions of all replica keys.

    This field includes the current KMS key if it is a replica key.
    """


class XksKeyConfigurationType(Boto3Model):
    """Information about the `external key <https://docs.aws.amazon.com/kms/latest/developerguide/keystore-
    external.html#concept-external-key>`_ that is associated with a KMS key in an external key store.

    This element appears in a CreateKey or DescribeKey response only for a KMS key in an external key store.

    The *external key* is a symmetric encryption key that is hosted by an external key manager outside of Amazon Web
    Services. When you use the KMS key in an external key store in a cryptographic operation, the cryptographic operation is
    performed in the external key manager using the specified external key. For more information, see `External
    key <https://docs.aws.amazon.com/kms/latest/developerguide/keystore-external.html#concept-external-key>`_ in the *Key
    Management Service Developer Guide*.
    """

    Id: str | None = None
    """
    The ID of the external key in its external key manager.

    This is the ID that the external key store proxy uses to identify the external key.
    """


class KMSKey(PrimaryBoto3Model):
    """
    Contains metadata about a KMS key.

    This data type is used as a response element for the CreateKey, DescribeKey, and
    ReplicateKey operations.
    """

    manager_class: ClassVar[Type[Boto3ModelManager]] = KMSKeyManager

    Enabled: bool | None = True
    """
    Specifies whether the KMS key is enabled.

    When ``KeyState`` is ``Enabled`` this value is true, otherwise it is false.
    """
    KeyUsage: Literal["SIGN_VERIFY", "ENCRYPT_DECRYPT", "GENERATE_VERIFY_MAC", "KEY_AGREEMENT"] | None = "ENCRYPT_DECRYPT"
    """
The `cryptographic operations <https://docs.aws.amazon.com/kms/latest/developerguide/kms-
cryptography.html#cryptographic-operations>`_ for which you can use the KMS key.
    """
    KeySpec: Literal["RSA_2048", "RSA_3072", "RSA_4096", "ECC_NIST_P256", "ECC_NIST_P384", "ECC_NIST_P521", "ECC_SECG_P256K1", "SYMMETRIC_DEFAULT", "HMAC_224", "HMAC_256", "HMAC_384", "HMAC_512", "SM2", "ML_DSA_44", "ML_DSA_65", "ML_DSA_87"] | None = "SYMMETRIC_DEFAULT"
    """
    Describes the type of key material in the KMS key.
    """
    AWSAccountId: str = Field(default=None, frozen=True)
    """
    The twelve-digit account ID of the Amazon Web Services account that owns the KMS
    key.
    """
    KeyId: str = Field(frozen=True)
    """
    The globally unique identifier for the KMS key.
    """
    Arn: str = Field(default=None, frozen=True)
    """
    The Amazon Resource Name (ARN) of the KMS key.

    For examples, see `Key Management Service
    (KMS) <https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arn-syntax-kms>`_ in the Example ARNs
    section of the *Amazon Web Services General Reference*.
    """
    CreationDate: datetime = Field(default=None, frozen=True)
    """
    The date and time when the KMS key was created.
    """
    Description: str | None = None
    """
    The description of the KMS key.
    """
    KeyState: Literal[
        "Creating",
        "Enabled",
        "Disabled",
        "PendingDeletion",
        "PendingImport",
        "PendingReplicaDeletion",
        "Unavailable",
        "Updating",
    ] = Field(default=None, frozen=True)
    """
    The current status of the KMS key.
    """
    DeletionDate: datetime = Field(default=None, frozen=True)
    """
    The date and time after which KMS deletes this KMS key.

    This value is present only when the KMS key is scheduled for
    deletion, that is, when its ``KeyState`` is ``PendingDeletion``.
    """
    ValidTo: datetime = Field(default=None, frozen=True)
    """
    The earliest time at which any imported key material permanently associated with
    this KMS key expires.

    When a key
    material expires, KMS deletes the key material and the KMS key becomes unusable. This value is present only for KMS keys
    whose ``Origin`` is ``EXTERNAL`` and the ``ExpirationModel`` is ``KEY_MATERIAL_EXPIRES``, otherwise this value is
    omitted.
    """
    Origin: Literal["AWS_KMS", "EXTERNAL", "AWS_CLOUDHSM", "EXTERNAL_KEY_STORE"] | None = None
    """
    The source of the key material for the KMS key.

    When this value is ``AWS_KMS``, KMS created the key material. When this
    value is ``EXTERNAL``, the key material was imported or the KMS key doesn't have any key material. When this value is
    ``AWS_CLOUDHSM``, the key material was created in the CloudHSM cluster associated with a custom key store.
    """
    CustomKeyStoreId: str | None = None
    """
A unique identifier for the `custom key store <https://docs.aws.amazon.com/kms/latest/developerguide/key-store-
overview.html>`_ that contains the KMS key. This field is present only when the KMS key is created in a custom key store.
    """
    CloudHsmClusterId: str = Field(default=None, frozen=True)
    """
    The cluster ID of the CloudHSM cluster that contains the key material for the KMS
    key.

    When you create a KMS key in an CloudHSM
    `custom key store <https://docs.aws.amazon.com/kms/latest/developerguide/key-store-overview.html>`_,
    KMS creates
    the key material for the KMS key in the associated CloudHSM cluster. This field is present only when the KMS key is
    created in an CloudHSM key store.
    """
    ExpirationModel: Literal["KEY_MATERIAL_EXPIRES", "KEY_MATERIAL_DOES_NOT_EXPIRE"] = (
        Field(default=None, frozen=True)
    )
    """
    Specifies whether the KMS key's key material expires.

    This value is present only when ``Origin`` is ``EXTERNAL``,
    otherwise this value is omitted.
    """
    KeyManager: Literal["AWS", "CUSTOMER"] = Field(default=None, frozen=True)
    """
    The manager of the KMS key.

    KMS keys in your Amazon Web Services account are either customer managed or Amazon
    Web Services managed. For more information about the difference, see
    `KMS keys <https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms_keys>`_
    in the *Key Management Service
    Developer Guide*.
    """
    CustomerMasterKeySpec: Literal["RSA_2048", "RSA_3072", "RSA_4096", "ECC_NIST_P256", "ECC_NIST_P384", "ECC_NIST_P521", "ECC_SECG_P256K1", "SYMMETRIC_DEFAULT", "HMAC_224", "HMAC_256", "HMAC_384", "HMAC_512", "SM2"] | None = None
    """
    Instead, use the ``KeySpec`` field.
    """
    EncryptionAlgorithms: List[
        Literal["SYMMETRIC_DEFAULT", "RSAES_OAEP_SHA_1", "RSAES_OAEP_SHA_256", "SM2PKE"]
    ] = Field(default_factory=list, frozen=True)
    """
    The encryption algorithms that the KMS key supports.

    You cannot use the KMS key with other encryption algorithms within KMS.
    """
    SigningAlgorithms: List[
        Literal[
            "RSASSA_PSS_SHA_256",
            "RSASSA_PSS_SHA_384",
            "RSASSA_PSS_SHA_512",
            "RSASSA_PKCS1_V1_5_SHA_256",
            "RSASSA_PKCS1_V1_5_SHA_384",
            "RSASSA_PKCS1_V1_5_SHA_512",
            "ECDSA_SHA_256",
            "ECDSA_SHA_384",
            "ECDSA_SHA_512",
            "SM2DSA",
            "ML_DSA_SHAKE_256",
        ]
    ] = Field(default_factory=list, frozen=True)
    """
    The signing algorithms that the KMS key supports.

    You cannot use the KMS key with other signing algorithms within KMS.
    """
    KeyAgreementAlgorithms: List[Literal["ECDH"]] = Field(
        default_factory=list, frozen=True
    )
    """
    The key agreement algorithm used to derive a shared secret.
    """
    MultiRegion: bool | None = None
    """
    Indicates whether the KMS key is a multi-Region (``True``) or regional (``False``)
    key.

    This value is ``True`` for
    multi-Region primary and replica keys and ``False`` for regional KMS keys.
    """
    MultiRegionConfiguration: KMSMultiRegionConfiguration = Field(
        default=None, frozen=True
    )
    """
    Lists the primary and replica keys in same multi-Region key.

    This field is present only when the value of the
    ``MultiRegion`` field is ``True``.
    """
    PendingDeletionWindowInDays: int = Field(default=None, frozen=True)
    """
    The waiting period before the primary key in a multi-Region key is deleted.

    This waiting period begins when the last of
    its replica keys is deleted. This value is present only when the ``KeyState`` of the KMS key is
    ``PendingReplicaDeletion``. That indicates that the KMS key is the primary key in a multi-Region key, it is scheduled
    for deletion, and it still has existing replica keys.
    """
    MacAlgorithms: List[
        Literal["HMAC_SHA_224", "HMAC_SHA_256", "HMAC_SHA_384", "HMAC_SHA_512"]
    ] = Field(default_factory=list, frozen=True)
    """
    The message authentication code (MAC) algorithm that the HMAC KMS key supports.
    """
    XksKeyConfiguration: XksKeyConfigurationType = Field(default=None, frozen=True)
    """
    Information about the external key that is associated with a KMS key in an external
    key store.
    """
    CurrentKeyMaterialId: str = Field(default=None, frozen=True)
    """
    Identifies the current key material.

    This value is present for symmetric encryption keys with ``AWS_KMS`` origin and
    single-Region, symmetric encryption keys with ``EXTERNAL`` origin. These KMS keys support automatic or on-demand key
    rotation and can have multiple key materials associated with them. KMS uses the current key material for both encryption
    and decryption, and the non-current key material for decryption operations only.
    """

    @property
    def pk(self) -> str | None:
        """
        Return the primary key of the model.   This is the value of the :py:attr:`KeyId`
        attribute.

        Returns:
            The primary key of the model instance.
        """
        return self.KeyId

    @property
    def arn(self) -> str | None:
        """
        Return the ARN of the model.   This is the value of the :py:attr:`Arn`
        attribute.

        Returns:
            The ARN of the model instance.
        """
        return self.Arn

    def __hash__(self) -> int:
        """
        Return the hash of the model.

        This is the value of the
        :py:attr:`KeyId` attribute.
        """
        return hash(self.KeyId)


# =======================
# Request/Response Models
# =======================


class CreateKeyResponse(Boto3Model):
    KeyMetadata: KMSKey | None = None
    """
    Metadata associated with the KMS key.
    """


class DescribeKeyResponse(Boto3Model):
    KeyMetadata: KMSKey | None = None
    """
    Metadata associated with the key.
    """


class KeyListEntry(Boto3Model):
    """
    Contains information about each entry in the key list.
    """

    KeyId: str | None = None
    """
    Unique identifier of the key.
    """
    KeyArn: str | None = None
    """
    ARN of the key.
    """


class ListKeysResponse(Boto3Model):
    Keys: List["KeyListEntry"] | None = None
    """
    A list of KMS keys.
    """
    NextMarker: str | None = None
    """
    When ``Truncated`` is true, this element is present and contains the value to use
    for the ``Marker`` parameter in a subsequent request.
    """
    Truncated: bool | None = None
    """
    A flag that indicates whether there are more items in the list.

    When this value is true, the list in this response is
    truncated. To get more items, pass the value of the ``NextMarker`` element in this response to the ``Marker`` parameter
    in a subsequent request.
    """


class ScheduleKeyDeletionResponse(Boto3Model):
    KeyId: str | None = None
    """
The Amazon Resource Name (`key ARN <https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN>`_)
of the KMS key whose deletion is scheduled.
    """
    DeletionDate: datetime | None = None
    """
    The date and time after which KMS deletes the KMS key.
    """
    KeyState: Literal["Creating", "Enabled", "Disabled", "PendingDeletion", "PendingImport", "PendingReplicaDeletion", "Unavailable", "Updating"] | None = None
    """
    The current status of the KMS key.
    """
    PendingWindowInDays: int | None = None
    """
    The waiting period before the KMS key is deleted.
    """


class CancelKeyDeletionResponse(Boto3Model):
    KeyId: str | None = None
    """
The Amazon Resource Name (`key ARN <https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN>`_)
of the KMS key whose deletion is canceled.
    """
