# This file is automatically generated by botocraft.  Do not edit directly.
# mypy: disable-error-code="index, override, assignment, union-attr, misc"
from botocraft.mixins.sqs import MessageModelMixin
from .common import Tag
from collections import OrderedDict
from botocraft.mixins.sqs import queue_recieve_messages_add_event_factory
from botocraft.mixins.sqs import QueueManagerMixin
from botocraft.eventbridge.factory import AbstractEventFactory, EventFactory
from botocraft.mixins.sqs import queue_list_urls_to_queues
from pydantic import Field
from botocraft.mixins.tags import TagsDictMixin
from .abstract import (
    Boto3Model,
    ReadonlyBoto3Model,
    PrimaryBoto3Model,
    ReadonlyPrimaryBoto3Model,
    Boto3ModelManager,
    ReadonlyBoto3ModelManager,
)
from .abstract import PrimaryBoto3ModelQuerySet
from datetime import datetime
from botocraft.mixins.sqs import queue_recieve_messages_add_queue_url
from botocraft.mixins.sqs import QueueModelMixin
from typing import ClassVar, Type, Optional, Literal, Dict, List, Union, Any, cast

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


class QueueManager(QueueManagerMixin, Boto3ModelManager):
    service_name: str = "sqs"

    def create(self, model: "Queue") -> str:
        """
        Creates a new standard or FIFO queue. You can pass one or more attributes in the
        request. Keep the following in mind:

        Args:
            model: The :py:class:`Queue` to create.
        """
        data = model.model_dump(exclude_none=True, by_alias=True)
        args = dict(
            QueueName=data.get("QueueName"),
            Attributes=data.get("Attributes"),
            tags=data.get("tags"),
        )
        _response = self.client.create_queue(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = CreateQueueResult(**_response)

        self.sessionize(response.QueueUrl)
        return cast("str", response.QueueUrl)

    def delete(self, QueueUrl: str) -> None:
        """
        Deletes the queue specified by the ``QueueUrl``, regardless of the queue's
        contents.

        Args:
            QueueUrl: The URL of the Amazon SQS queue to delete.
        """
        args: Dict[str, Any] = dict(QueueUrl=self.serialize(QueueUrl))
        self.client.delete_queue(**{k: v for k, v in args.items() if v is not None})

    @queue_list_urls_to_queues
    def list(self, *, QueueNamePrefix: str | None = None) -> List[str]:
        """
        Returns a list of your queues in the current region. The response includes a
        maximum of 1,000 results. If you specify a value for the optional
        ``QueueNamePrefix`` parameter, only queues with a name that begins with the
        specified value are returned.

        Keyword Args:
            QueueNamePrefix: A string to use for filtering the list results. Only those queues whose name begins with the
                specified string are returned.
        """
        paginator = self.client.get_paginator("list_queues")
        args: Dict[str, Any] = dict(QueueNamePrefix=self.serialize(QueueNamePrefix))
        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 = ListQueuesResult(**_response)
            if response.QueueUrls:
                results.extend(response.QueueUrls)
            else:
                if getattr(response, "NextToken", None):
                    continue
                break
        self.sessionize(results)
        if results and isinstance(results[0], Boto3Model):
            return PrimaryBoto3ModelQuerySet(results)
        return results

    def purge(self, QueueUrl: str) -> "None":
        """
        Deletes available messages in a queue (including in-flight messages) specified
        by the ``QueueURL`` parameter.

        Args:
            QueueUrl: The URL of the queue from which the ``PurgeQueue`` action deletes messages.
        """
        args: Dict[str, Any] = dict(QueueUrl=self.serialize(QueueUrl))
        self.client.purge_queue(**{k: v for k, v in args.items() if v is not None})

    def add_permission(
        self, QueueUrl: str, Label: str, AWSAccountIds: List[str], Actions: List[str]
    ) -> "None":
        """
        Adds a permission to a queue for a specific `principal <https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#P>`_.
        This allows sharing access to the queue.

        Args:
            QueueUrl: The URL of the Amazon SQS queue to which permissions are added.
            Label: The unique identification of the permission you're setting (for example, ``AliceSendMessage``). Maximum 80
                characters. Allowed characters include alphanumeric characters, hyphens (``-``), and underscores (``_``).
            AWSAccountIds: The Amazon Web Services account numbers of the `principals
                <https://docs.aws.amazon.com/general/latest/gr/glos- chap.html#P>`_ who are to receive permission. For information
                about locating the Amazon Web Services account identification, see `Your Amazon Web Services Identifiers
                <https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-making-api- requests.html#sqs-api-
                request-authentication>`_ in the *Amazon SQS Developer Guide*.
            Actions: The action the client wants to allow for the specified principal. Valid values: the name of any action or
                ``*``.

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

    def remove_permission(self, QueueUrl: str, Label: str) -> "None":
        """
        Revokes any permissions in the queue policy that matches the specified ``Label``
        parameter.

        Args:
            QueueUrl: The URL of the Amazon SQS queue from which permissions are removed.
            Label: The identification of the permission to remove. This is the label added using the  ``AddPermission``  action.
        """
        args: Dict[str, Any] = dict(
            QueueUrl=self.serialize(QueueUrl), Label=self.serialize(Label)
        )
        self.client.remove_permission(
            **{k: v for k, v in args.items() if v is not None}
        )

    def delete_message(self, QueueUrl: str, ReceiptHandle: str) -> "None":
        """
        Deletes the specified message from the specified queue. To select the message to
        delete, use the ``ReceiptHandle`` of the message (*not* the ``MessageId`` which
        you receive when you send the message). Amazon SQS can delete a message from a
        queue even if a visibility timeout setting causes the message to be locked by
        another consumer. Amazon SQS automatically deletes messages left in a queue
        longer than the retention period configured for the queue.

        Args:
            QueueUrl: The URL of the Amazon SQS queue from which messages are deleted.
            ReceiptHandle: The receipt handle associated with the message to delete.
        """
        args: Dict[str, Any] = dict(
            QueueUrl=self.serialize(QueueUrl),
            ReceiptHandle=self.serialize(ReceiptHandle),
        )
        self.client.delete_message(**{k: v for k, v in args.items() if v is not None})

    @queue_recieve_messages_add_queue_url
    @queue_recieve_messages_add_event_factory
    def receive_messages(
        self,
        QueueUrl: str,
        *,
        AttributeNames: List[Literal["All", "Policy", "VisibilityTimeout", "MaximumMessageSize", "MessageRetentionPeriod", "ApproximateNumberOfMessages", "ApproximateNumberOfMessagesNotVisible", "CreatedTimestamp", "LastModifiedTimestamp", "QueueArn", "ApproximateNumberOfMessagesDelayed", "DelaySeconds", "ReceiveMessageWaitTimeSeconds", "RedrivePolicy", "FifoQueue", "ContentBasedDeduplication", "KmsMasterKeyId", "KmsDataKeyReusePeriodSeconds", "DeduplicationScope", "FifoThroughputLimit", "RedriveAllowPolicy", "SqsManagedSseEnabled"]] | None = None,
        MessageSystemAttributeNames: List[Literal["All", "SenderId", "SentTimestamp", "ApproximateReceiveCount", "ApproximateFirstReceiveTimestamp", "SequenceNumber", "MessageDeduplicationId", "MessageGroupId", "AWSTraceHeader", "DeadLetterQueueSourceArn"]] | None = None,
        MessageAttributeNames: List[str] | None = None,
        MaxNumberOfMessages: int | None = None,
        VisibilityTimeout: int | None = None,
        WaitTimeSeconds: int | None = None,
        ReceiveRequestAttemptId: str | None = None,
        EventFactoryClass: Type[AbstractEventFactory] | None = None,
    ) -> List["Message"]:
        """
        Retrieves one or more messages (up to 10), from the specified queue. Using the ``WaitTimeSeconds`` parameter enables
        long-poll support. For more information, see `Amazon SQS Long
        Polling <https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-long-polling.html>`_ in the
        *Amazon SQS Developer Guide*.

        Args:
            QueueUrl: The URL of the Amazon SQS queue from which messages are received.

        Keyword Args:
            AttributeNames: This parameter has been discontinued but will be supported for backward compatibility. To provide
                attribute names, you are encouraged to use ``MessageSystemAttributeNames``.
            MessageSystemAttributeNames: A list of attributes that need to be returned along with each message. These attributes
                include:
            MessageAttributeNames: The name of the message attribute, where *N* is the index.
            MaxNumberOfMessages: The maximum number of messages to return. Amazon SQS never returns more messages than this
                value (however, fewer messages might be returned). Valid values: 1 to 10. Default: 1.
            VisibilityTimeout: The duration (in seconds) that the received messages are hidden from subsequent retrieve requests
                after being retrieved by a ``ReceiveMessage`` request. If not specified, the default visibility timeout for the
                queue is used, which is 30 seconds.
            WaitTimeSeconds: The duration (in seconds) for which the call waits for a message to arrive in the queue before
                returning. If a message is available, the call returns sooner than ``WaitTimeSeconds``. If no messages are available
                and the wait time expires, the call does not return a message list. If you are using the Java SDK, it returns a
                ``ReceiveMessageResponse`` object, which has a empty list instead of a Null object.
            ReceiveRequestAttemptId: This parameter applies only to FIFO (first-in-first-out) queues.
            EventFactoryClass: the value to set for EventFactoryClass

        """
        args: Dict[str, Any] = dict(
            QueueUrl=self.serialize(QueueUrl),
            AttributeNames=self.serialize(AttributeNames),
            MessageSystemAttributeNames=self.serialize(MessageSystemAttributeNames),
            MessageAttributeNames=self.serialize(MessageAttributeNames),
            MaxNumberOfMessages=self.serialize(MaxNumberOfMessages),
            VisibilityTimeout=self.serialize(VisibilityTimeout),
            WaitTimeSeconds=self.serialize(WaitTimeSeconds),
            ReceiveRequestAttemptId=self.serialize(ReceiveRequestAttemptId),
        )
        _response = self.client.receive_message(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = ReceiveMessageResult(**_response)

        results: List["Message"] = None
        if response is not None:
            results = response.Messages

        self.sessionize(results)
        return cast("List[Message]", results)

    def batch_send_messages(
        self, QueueUrl: str, Entries: List["SendMessageBatchRequestEntry"]
    ) -> "SendMessageBatchResult":
        """
        You can use ``SendMessageBatch`` to send up to 10 messages to the specified
        queue by assigning either identical or different values to each message (or by
        not assigning values at all). This is a batch version of  ``SendMessage.`` For a
        FIFO queue, multiple messages within a single batch are enqueued in the order
        they are sent.

        Args:
            QueueUrl: The URL of the Amazon SQS queue to which batched messages are sent.
            Entries: A list of  ``SendMessageBatchRequestEntry``  items.
        """
        args: Dict[str, Any] = dict(
            QueueUrl=self.serialize(QueueUrl), Entries=self.serialize(Entries)
        )
        _response = self.client.send_message_batch(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = SendMessageBatchResult(**_response)

        results: "SendMessageBatchResult" = None
        if response is not None:
            results = response

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

    def batch_delete_messages(
        self, QueueUrl: str, Entries: List["DeleteMessageBatchRequestEntry"]
    ) -> "DeleteMessageBatchResult":
        """
        Deletes up to ten messages from the specified queue. This is a batch version of
        ``DeleteMessage.`` The result of the action on each message is reported
        individually in the response.

        Args:
            QueueUrl: The URL of the Amazon SQS queue from which messages are deleted.
            Entries: Lists the receipt handles for the messages to be deleted.
        """
        args: Dict[str, Any] = dict(
            QueueUrl=self.serialize(QueueUrl), Entries=self.serialize(Entries)
        )
        _response = self.client.delete_message_batch(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = DeleteMessageBatchResult(**_response)

        results: "DeleteMessageBatchResult" = None
        if response is not None:
            results = response

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

    def change_message_visibility(
        self, QueueUrl: str, ReceiptHandle: str, VisibilityTimeout: int
    ) -> "None":
        """
        Changes the visibility timeout of a specified message in a queue to a new value. The default visibility timeout for a
        message is 30 seconds. The minimum is 0 seconds. The maximum is 12 hours. For more information, see `Visibility
        Timeout <https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html>`_ in the
        *Amazon SQS Developer Guide*.

        Args:
            QueueUrl: The URL of the Amazon SQS queue whose message's visibility is changed.
            ReceiptHandle: The receipt handle associated with the message, whose visibility timeout is changed. This parameter
                is returned by the ``ReceiveMessage``  action.
            VisibilityTimeout: The new value for the message's visibility timeout (in seconds). Values range: ``0`` to
                ``43200``. Maximum: 12 hours.

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

    def change_message_visibility_batch(
        self, QueueUrl: str, Entries: List["ChangeMessageVisibilityBatchRequestEntry"]
    ) -> "ChangeMessageVisibilityBatchResult":
        """
        Changes the visibility timeout of multiple messages. This is a batch version of
        ``ChangeMessageVisibility.`` The result of the action on each message is
        reported individually in the response. You can send up to 10
        ``ChangeMessageVisibility``  requests with each ``ChangeMessageVisibilityBatch``
        action.

        Args:
            QueueUrl: The URL of the Amazon SQS queue whose messages' visibility is changed.
            Entries: Lists the receipt handles of the messages for which the visibility timeout must be changed.
        """
        args: Dict[str, Any] = dict(
            QueueUrl=self.serialize(QueueUrl), Entries=self.serialize(Entries)
        )
        _response = self.client.change_message_visibility_batch(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = ChangeMessageVisibilityBatchResult(**_response)

        results: "ChangeMessageVisibilityBatchResult" = None
        if response is not None:
            results = response

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


class MessageManager(Boto3ModelManager):
    service_name: str = "sqs"

    def send(
        self,
        QueueUrl: str,
        MessageBody: str,
        *,
        DelaySeconds: int | None = None,
        MessageAttributes: Dict[str, "MessageAttributeValue"] | None = None,
        MessageSystemAttributes: Dict[Literal["AWSTraceHeader"], "MessageSystemAttributeValue"] | None = None,
        MessageDeduplicationId: str | None = None,
        MessageGroupId: str | None = None,
    ) -> str:
        """
        Delivers a message to the specified queue.

        Args:
            QueueUrl: The URL of the Amazon SQS queue to which a message is sent.
            MessageBody: The message to send. The minimum size is one character. The maximum size is 1 MiB or 1,048,576 bytes

        Keyword Args:
            DelaySeconds: The length of time, in seconds, for which to delay a specific message. Valid values: 0 to 900.
                Maximum: 15 minutes. Messages with a positive ``DelaySeconds`` value become available for processing after the delay
                period is finished. If you don't specify a value, the default value for the queue applies.
            MessageAttributes: Each message attribute consists of a ``Name``, ``Type``, and ``Value``. For more information, see
                `Amazon SQS message attributes <https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-
                message-metadata.html#sqs- message-attributes>`_ in the *Amazon SQS Developer Guide*.
            MessageSystemAttributes: The message system attribute to send. Each message system attribute consists of a ``Name``,
                ``Type``, and ``Value``.
            MessageDeduplicationId: This parameter applies only to FIFO (first-in-first-out) queues.
            MessageGroupId: ``MessageGroupId`` is an attribute used in Amazon SQS FIFO (First-In-First-Out) and standard queues.
                In FIFO queues, ``MessageGroupId`` organizes messages into distinct groups. Messages within the same message group
                are always processed one at a time, in strict order, ensuring that no two messages from the same group are processed
                simultaneously. In standard queues, using ``MessageGroupId`` enables fair queues. It is used to identify the tenant
                a message belongs to, helping maintain consistent message dwell time across all tenants during noisy neighbor
                events. Unlike FIFO queues, messages with the same ``MessageGroupId`` can be processed in parallel, maintaining the
                high throughput of standard queues.
        """
        args: Dict[str, Any] = dict(
            QueueUrl=self.serialize(QueueUrl),
            MessageBody=self.serialize(MessageBody),
            DelaySeconds=self.serialize(DelaySeconds),
            MessageAttributes=self.serialize(MessageAttributes),
            MessageSystemAttributes=self.serialize(MessageSystemAttributes),
            MessageDeduplicationId=self.serialize(MessageDeduplicationId),
            MessageGroupId=self.serialize(MessageGroupId),
        )
        _response = self.client.send_message(
            **{k: v for k, v in args.items() if v is not None}
        )
        response = SendMessageResult(**_response)

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

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

    def delete(self, QueueUrl: str, ReceiptHandle: str) -> None:
        """
        Deletes the specified message from the specified queue. To select the message to
        delete, use the ``ReceiptHandle`` of the message (*not* the ``MessageId`` which
        you receive when you send the message). Amazon SQS can delete a message from a
        queue even if a visibility timeout setting causes the message to be locked by
        another consumer. Amazon SQS automatically deletes messages left in a queue
        longer than the retention period configured for the queue.

        Args:
            QueueUrl: The URL of the Amazon SQS queue from which messages are deleted.
            ReceiptHandle: The receipt handle associated with the message to delete.
        """
        args: Dict[str, Any] = dict(
            QueueUrl=self.serialize(QueueUrl),
            ReceiptHandle=self.serialize(ReceiptHandle),
        )
        self.client.delete_message(**{k: v for k, v in args.items() if v is not None})


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


class Queue(TagsDictMixin, QueueModelMixin, PrimaryBoto3Model):
    tag_class: ClassVar[Type] = Tag
    manager_class: ClassVar[Type[Boto3ModelManager]] = QueueManager

    QueueUrl: str
    """
    The URL of the queue.

    This is a unique identifier for the queue.
    """
    QueueName: str
    """
    The name of the queue.

    This is a unique identifier for the queue.
    """
    Attributes: Dict[str, str] | None = None
    """
    The attributes of the queue.

    This is a dictionary of attribute names and values.
    """
    Tags: List[Tag] = Field(default_factory=list, alias="tags")
    """
    The tags of the queue.

    This is a list of Tag objects.
    """

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

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

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

        Returns:
            The name of the model instance.
        """
        return self.QueueName

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

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

    def purge(self) -> "None":
        """
        Purge the queue.
        """

        return (
            cast("QueueManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .purge(
                cast("str", self.QueueUrl),
            )
        )

    def add_permission(
        self, Label: str, AWSAccountIds: List[str], Actions: List[str]
    ) -> "None":
        """
        Add permission to the queue.

        Args:
            Label: The unique identification of the permission you're setting (for example, ``AliceSendMessage``). Maximum 80
                characters. Allowed characters include alphanumeric characters, hyphens (``-``), and underscores (``_``).
            AWSAccountIds: The Amazon Web Services account numbers of the `principals
                <https://docs.aws.amazon.com/general/latest/gr/glos- chap.html#P>`_ who are to receive permission. For information
                about locating the Amazon Web Services account identification, see `Your Amazon Web Services Identifiers
                <https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-making-api- requests.html#sqs-api-
                request-authentication>`_ in the *Amazon SQS Developer Guide*.
            Actions: The action the client wants to allow for the specified principal. Valid values: the name of any action or
                ``*``.
        """

        return (
            cast("QueueManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .add_permission(
                cast("str", self.QueueUrl),
                Label,
                AWSAccountIds,
                Actions,
            )
        )

    def remove_permission(self, Label: str) -> "None":
        """
        Remove permission from the queue.

        Args:
            Label: The identification of the permission to remove. This is the label added using the  ``AddPermission``  action.
        """

        return (
            cast("QueueManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .remove_permission(
                cast("str", self.QueueUrl),
                Label,
            )
        )

    def receive(
        self,
        MessageAttributeNames: List[str] | None = None,
        MaxNumberOfMessages: int | None = None,
        VisibilityTimeout: int | None = None,
        WaitTimeSeconds: int | None = None,
        ReceiveRequestAttemptId: str | None = None,
        EventFactoryClass: Type[AbstractEventFactory] | None = None,
    ) -> List["Message"]:
        """
        Receive messages from the queue.

        Keyword Args:
            MessageAttributeNames: The name of the message attribute, where *N* is the index.
            MaxNumberOfMessages: The maximum number of messages to return. Amazon SQS never returns more messages than this
                value (however, fewer messages might be returned). Valid values: 1 to 10. Default: 1.
            VisibilityTimeout: The duration (in seconds) that the received messages are hidden from subsequent retrieve requests
                after being retrieved by a ``ReceiveMessage`` request. If not specified, the default visibility timeout for the
                queue is used, which is 30 seconds.
            WaitTimeSeconds: The duration (in seconds) for which the call waits for a message to arrive in the queue before
                returning. If a message is available, the call returns sooner than ``WaitTimeSeconds``. If no messages are available
                and the wait time expires, the call does not return a message list. If you are using the Java SDK, it returns a
                ``ReceiveMessageResponse`` object, which has a empty list instead of a Null object.
            ReceiveRequestAttemptId: This parameter applies only to FIFO (first-in-first-out) queues.
            EventFactoryClass: the value to set for EventFactoryClass
        """

        return (
            cast("QueueManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .receive_messages(
                cast("str", self.QueueUrl),
                MessageAttributeNames=MessageAttributeNames,
                MaxNumberOfMessages=MaxNumberOfMessages,
                VisibilityTimeout=VisibilityTimeout,
                WaitTimeSeconds=WaitTimeSeconds,
                ReceiveRequestAttemptId=ReceiveRequestAttemptId,
                EventFactoryClass=EventFactoryClass,
            )
        )


class MessageAttributeValue(Boto3Model):
    """
    The user-specified message attribute value. For string data types, the ``Value``
    attribute has the same restrictions on the content as the message body. For more
    information, see  ``SendMessage.``

    ``Name``, ``type``, ``value`` and the message body must not be empty or null. All parts of the message attribute,
    including ``Name``, ``Type``, and ``Value``, are part of the message size restriction (1 MiB or 1,048,576 bytes).
    """

    StringValue: str | None = None
    """
    Strings are Unicode with UTF-8 binary encoding.

    For a list of code values, see
    `ASCII Printable Characters <http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters>`_.
    """
    BinaryValue: bytes | None = None
    """
    Binary type attributes can store any binary data, such as compressed data, encrypted
    data, or images.
    """
    StringListValues: List[str] | None = None
    """
    Not implemented.

    Reserved for future use.
    """
    BinaryListValues: List[bytes] | None = None
    """
    Not implemented.

    Reserved for future use.
    """
    DataType: str
    """
Amazon SQS supports the following logical data types: ``String``, ``Number``, and ``Binary``. For the ``Number`` data
type, you must use ``StringValue``.
    """


class MessageSystemAttributeValue(Boto3Model):
    """
    The user-specified message system attribute value. For string data types, the
    ``Value`` attribute has the same restrictions on the content as the message body.
    For more information, see  ``SendMessage.``

    ``Name``, ``type``, ``value`` and the message body must not be empty or null.
    """

    StringValue: str | None = None
    """
    Strings are Unicode with UTF-8 binary encoding.

    For a list of code values, see
    `ASCII Printable Characters <http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters>`_.
    """
    BinaryValue: bytes | None = None
    """
    Binary type attributes can store any binary data, such as compressed data, encrypted
    data, or images.
    """
    StringListValues: List[str] | None = None
    """
    Not implemented.

    Reserved for future use.
    """
    BinaryListValues: List[bytes] | None = None
    """
    Not implemented.

    Reserved for future use.
    """
    DataType: str
    """
Amazon SQS supports the following logical data types: ``String``, ``Number``, and ``Binary``. For the ``Number`` data
type, you must use ``StringValue``.
    """


class Message(MessageModelMixin, PrimaryBoto3Model):
    """
    An Amazon SQS message.
    """

    manager_class: ClassVar[Type[Boto3ModelManager]] = MessageManager

    MessageId: str | None = None
    """
    A unique identifier for the message.

    A ``MessageId``is considered unique across all Amazon Web Services accounts for an
    extended period of time.
    """
    ReceiptHandle: str | None = None
    """
    An identifier associated with the act of receiving the message.

    A new receipt handle is returned every time you receive a message. When deleting a
    message, you provide the last received receipt handle to delete the message.
    """
    MD5OfBody: str | None = None
    """
    An MD5 digest of the non-URL-encoded message body string.
    """
    Body: str | None = None
    """
    The message's contents (not URL-encoded).
    """
    Attributes: Dict[Literal["All", "SenderId", "SentTimestamp", "ApproximateReceiveCount", "ApproximateFirstReceiveTimestamp", "SequenceNumber", "MessageDeduplicationId", "MessageGroupId", "AWSTraceHeader", "DeadLetterQueueSourceArn"], str] | None = None
    """
    A map of the attributes requested in  ``ReceiveMessage``  to their respective
    values.

    Supported attributes:
    """
    MD5OfMessageAttributes: str | None = None
    """
    An MD5 digest of the non-URL-encoded message attribute string.

    You can use this attribute to verify that Amazon SQS received the message correctly.
    Amazon SQS URL-decodes the message before creating the MD5 digest. For information
    about MD5, see
    `RFC1321 <https://www.ietf.org/rfc/rfc1321.txt>`_.
    """
    MessageAttributes: Dict[str, "MessageAttributeValue"] | None = None
    """
    Each message attribute consists of a ``Name``, ``Type``, and ``Value``.

    For more information, see
    `Amazon SQS message attributes <https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-metadata.html#sqs-
    message-attributes>`_ in the *Amazon SQS Developer Guide*.
    """
    QueueUrl: str | None = None
    """
    The URL of the queue.

    This is a unique identifier for the queue.
    """
    EventFactoryClass: Type[AbstractEventFactory] | None = EventFactory
    """
    The factory class for the event.

    This is used to create events from messages received from the queue.
    """

    @property
    def pk(self) -> OrderedDict[str, Any]:
        """
        The primary key of the message.

        This can be used to delete the message from its queue with the :py:meth:`botocraft.services.sqs.MessageManager.delete` method.
        """

        return OrderedDict(
            {
                "QueueUrl": self.QueueUrl,
                "ReceiptHandle": self.ReceiptHandle,
            }
        )

    def send(
        self,
        DelaySeconds: int | None = None,
        MessageDeduplicationId: str | None = None,
        MessageGroupId: str | None = None,
    ) -> "str":
        """
        Send this message to the queue.

        Keyword Args:
            DelaySeconds: The length of time, in seconds, for which to delay a specific message. Valid values: 0 to 900.
                Maximum: 15 minutes. Messages with a positive ``DelaySeconds`` value become available for processing after the delay
                period is finished. If you don't specify a value, the default value for the queue applies.
            MessageDeduplicationId: This parameter applies only to FIFO (first-in-first-out) queues.
            MessageGroupId: ``MessageGroupId`` is an attribute used in Amazon SQS FIFO (First-In-First-Out) and standard queues.
                In FIFO queues, ``MessageGroupId`` organizes messages into distinct groups. Messages within the same message group
                are always processed one at a time, in strict order, ensuring that no two messages from the same group are processed
                simultaneously. In standard queues, using ``MessageGroupId`` enables fair queues. It is used to identify the tenant
                a message belongs to, helping maintain consistent message dwell time across all tenants during noisy neighbor
                events. Unlike FIFO queues, messages with the same ``MessageGroupId`` can be processed in parallel, maintaining the
                high throughput of standard queues.
        """

        return (
            cast("MessageManager", self.objects)  # type: ignore[attr-defined]
            .using(self.session)
            .send(
                cast("str", self.QueueUrl),
                cast("str", self.MessageBody),
                MessageAttributes=cast(
                    "Dict[str, MessageAttributeValue] | None", self.MessageAttributes
                ),
                DelaySeconds=DelaySeconds,
                MessageDeduplicationId=MessageDeduplicationId,
                MessageGroupId=MessageGroupId,
            )
        )


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


class CreateQueueResult(Boto3Model):
    """
    Returns the ``QueueUrl`` attribute of the created queue.
    """

    QueueUrl: str | None = None
    """
    The URL of the created Amazon SQS queue.
    """


class ListQueuesResult(Boto3Model):
    """
    A list of your queues.
    """

    QueueUrls: List[str] | None = None
    """
    A list of queue URLs, up to 1,000 entries, or the value of ``MaxResults`` that you
    sent in the request.
    """
    NextToken: str | None = None
    """
    Pagination token to include in the next request.

    Token value is ``null`` if there are no additional results to request,
    or if you did not set ``MaxResults`` in the request.
    """


class ReceiveMessageResult(Boto3Model):
    """
    A list of received messages.
    """

    Messages: List["Message"] | None = None
    """
    A list of messages.
    """


class SendMessageBatchRequestEntry(Boto3Model):
    """
    Contains the details of a single Amazon SQS message along with an ``Id``.
    """

    Id: str
    """
    An identifier for a message in this batch used to communicate the result.
    """
    MessageBody: str
    """
    The body of the message.
    """
    DelaySeconds: int | None = None
    """
    The length of time, in seconds, for which a specific message is delayed.

    Valid values: 0 to 900. Maximum: 15 minutes.
    Messages with a positive ``DelaySeconds`` value become available for processing after the delay period is finished. If
    you don't specify a value, the default value for the queue is applied.
    """
    MessageAttributes: Dict[str, "MessageAttributeValue"] | None = None
    """
    Each message attribute consists of a ``Name``, ``Type``, and ``Value``.

    For more information, see
    `Amazon SQS message attributes <https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-metadata.html#sqs-
    message-attributes>`_ in the *Amazon SQS Developer Guide*.
    """
    MessageSystemAttributes: Dict[Literal["AWSTraceHeader"], "MessageSystemAttributeValue"] | None = None
    """
    The message system attribute to send Each message system attribute consists of a
    ``Name``, ``Type``, and ``Value``.
    """
    MessageDeduplicationId: str | None = None
    """
    This parameter applies only to FIFO (first-in-first-out) queues.
    """
    MessageGroupId: str | None = None
    """
    ``MessageGroupId`` is an attribute used in Amazon SQS FIFO (First-In-First-Out) and
    standard queues.

    In FIFO queues,
    ``MessageGroupId`` organizes messages into distinct groups. Messages within the same message group are always processed
    one at a time, in strict order, ensuring that no two messages from the same group are processed simultaneously. In
    standard queues, using ``MessageGroupId`` enables fair queues. It is used to identify the tenant a message belongs to,
    helping maintain consistent message dwell time across all tenants during noisy neighbor events. Unlike FIFO queues,
    messages with the same ``MessageGroupId`` can be processed in parallel, maintaining the high throughput of standard
    queues.
    """


class SendMessageBatchResultEntry(Boto3Model):
    """
    Encloses a ``MessageId`` for a successfully-enqueued message in a
    ``SendMessageBatch.``
    """

    Id: str
    """
    An identifier for the message in this batch.
    """
    MessageId: str
    """
    An identifier for the message.
    """
    MD5OfMessageBody: str
    """
    An MD5 digest of the non-URL-encoded message body string.

    You can use this attribute to verify that Amazon SQS received the message correctly.
    Amazon SQS URL-decodes the message before creating the MD5 digest. For information
    about MD5, see
    `RFC1321 <https://www.ietf.org/rfc/rfc1321.txt>`_.
    """
    MD5OfMessageAttributes: str | None = None
    """
    An MD5 digest of the non-URL-encoded message attribute string.

    You can use this attribute to verify that Amazon SQS received the message correctly.
    Amazon SQS URL-decodes the message before creating the MD5 digest. For information
    about MD5, see
    `RFC1321 <https://www.ietf.org/rfc/rfc1321.txt>`_.
    """
    MD5OfMessageSystemAttributes: str | None = None
    """
    An MD5 digest of the non-URL-encoded message system attribute string.

    You can use this attribute to verify that Amazon SQS received the message correctly.
    Amazon SQS URL-decodes the message before creating the MD5 digest. For information
    about MD5, see
    `RFC1321 <https://www.ietf.org/rfc/rfc1321.txt>`_.
    """
    SequenceNumber: str | None = None
    """
    This parameter applies only to FIFO (first-in-first-out) queues.
    """


class BatchResultErrorEntry(Boto3Model):
    """
    Gives a detailed description of the result of an action on each entry in the
    request.
    """

    Id: str
    """
    The ``Id`` of an entry in a batch request.
    """
    SenderFault: bool
    """
    Specifies whether the error happened due to the caller of the batch API action.
    """
    Code: str
    """
    An error code representing why the action failed on this entry.
    """
    Message: str | None = None
    """
    A message explaining why the action failed on this entry.
    """


class SendMessageBatchResult(Boto3Model):
    """
    For each message in the batch, the response contains a
    ``SendMessageBatchResultEntry``  tag if the message succeeds or a
    ``BatchResultErrorEntry``  tag if the message fails.
    """

    Successful: List["SendMessageBatchResultEntry"]
    """
    A list of  ``SendMessageBatchResultEntry``  items.
    """
    Failed: List["BatchResultErrorEntry"]
    """
    A list of  ``BatchResultErrorEntry``  items with error details about each message
    that can't be enqueued.
    """


class DeleteMessageBatchRequestEntry(Boto3Model):
    """
    Encloses a receipt handle and an identifier for it.
    """

    Id: str
    """
    The identifier for this particular receipt handle.

    This is used to communicate the result.
    """
    ReceiptHandle: str
    """
    A receipt handle.
    """


class DeleteMessageBatchResultEntry(Boto3Model):
    """
    Encloses the ``Id`` of an entry in  ``DeleteMessageBatch.``
    """

    Id: str
    """
    Represents a successfully deleted message.
    """


class DeleteMessageBatchResult(Boto3Model):
    """
    For each message in the batch, the response contains a
    ``DeleteMessageBatchResultEntry``  tag if the message is deleted or a
    ``BatchResultErrorEntry``  tag if the message can't be deleted.
    """

    Successful: List["DeleteMessageBatchResultEntry"]
    """
    A list of  ``DeleteMessageBatchResultEntry``  items.
    """
    Failed: List["BatchResultErrorEntry"]
    """
    A list of  ``BatchResultErrorEntry``  items.
    """


class ChangeMessageVisibilityBatchRequestEntry(Boto3Model):
    """
    Encloses a receipt handle and an entry ID for each message in
    ``ChangeMessageVisibilityBatch.``
    """

    Id: str
    """
    An identifier for this particular receipt handle used to communicate the result.
    """
    ReceiptHandle: str
    """
    A receipt handle.
    """
    VisibilityTimeout: int | None = None
    """
    The new value (in seconds) for the message's visibility timeout.
    """


class ChangeMessageVisibilityBatchResultEntry(Boto3Model):
    """
    Encloses the ``Id`` of an entry in  ``ChangeMessageVisibilityBatch.``
    """

    Id: str
    """
    Represents a message whose visibility timeout has been changed successfully.
    """


class ChangeMessageVisibilityBatchResult(Boto3Model):
    """
    For each message in the batch, the response contains a
    ``ChangeMessageVisibilityBatchResultEntry``  tag if the message succeeds or a
    ``BatchResultErrorEntry``  tag if the message fails.
    """

    Successful: List["ChangeMessageVisibilityBatchResultEntry"]
    """
    A list of  ``ChangeMessageVisibilityBatchResultEntry``  items.
    """
    Failed: List["BatchResultErrorEntry"]
    """
    A list of  ``BatchResultErrorEntry``  items.
    """


class SendMessageResult(Boto3Model):
    """
    The ``MD5OfMessageBody`` and ``MessageId`` elements.
    """

    MD5OfMessageBody: str | None = None
    """
    An MD5 digest of the non-URL-encoded message body string.

    You can use this attribute to verify that Amazon SQS received the message correctly.
    Amazon SQS URL-decodes the message before creating the MD5 digest. For information
    about MD5, see
    `RFC1321 <https://www.ietf.org/rfc/rfc1321.txt>`_.
    """
    MD5OfMessageAttributes: str | None = None
    """
    An MD5 digest of the non-URL-encoded message attribute string.

    You can use this attribute to verify that Amazon SQS received the message correctly.
    Amazon SQS URL-decodes the message before creating the MD5 digest. For information
    about MD5, see
    `RFC1321 <https://www.ietf.org/rfc/rfc1321.txt>`_.
    """
    MD5OfMessageSystemAttributes: str | None = None
    """
    An MD5 digest of the non-URL-encoded message system attribute string.

    You can use this attribute to verify that Amazon SQS received the message correctly.
    Amazon SQS URL-decodes the message before creating the MD5 digest.
    """
    MessageId: str | None = None
    """
    An attribute containing the ``MessageId`` of the message sent to the queue.

    For more information, see
    `Queue and Message Identifiers <https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-queue-message-
    identifiers.html>`_ in the *Amazon SQS Developer Guide*.
    """
    SequenceNumber: str | None = None
    """
    This parameter applies only to FIFO (first-in-first-out) queues.
    """
