"""
SQS client for job queue operations.

Single Responsibility: Send and receive messages from job queue.
"""

import json
import os
from typing import Optional

import boto3
from botocore.exceptions import ClientError


class SQSClient:
    """
    Thin wrapper around boto3 SQS client.

    Handles job queue message operations.
    Max 4 methods per CLAUDE.md guidelines.
    """

    def __init__(self, queue_url: str, region_name: str = "us-east-1"):
        """
        Initialize SQS client.

        Args:
            queue_url: SQS queue URL
            region_name: AWS region
        """
        self.queue_url = queue_url

        # Use session to respect AWS_PROFILE environment variable
        session = boto3.Session(
            profile_name=os.getenv("AWS_PROFILE"),
            region_name=region_name
        )
        self.sqs = session.client("sqs")

    def send_message(
        self, message: dict, message_group_id: str
    ) -> str:
        """
        Send message to FIFO queue.

        Args:
            message: Message payload (dict, will be JSON serialized)
            message_group_id: FIFO message group ID (typically dataset_name)

        Returns:
            Message ID

        Raises:
            ClientError: If SQS operation fails
        """
        try:
            print(f"DEBUG: Sending message to SQS queue: {self.queue_url}")
            print(f"DEBUG: MessageGroupId: {message_group_id}")
            print(f"DEBUG: Message: {json.dumps(message)[:200]}...")

            # Use job_id as MessageDeduplicationId to ensure uniqueness
            # This prevents duplicate jobs from being deduplicated
            deduplication_id = message.get("job_id", "")
            print(f"DEBUG: MessageDeduplicationId: {deduplication_id}")

            response = self.sqs.send_message(
                QueueUrl=self.queue_url,
                MessageBody=json.dumps(message),
                MessageGroupId=message_group_id,
                MessageDeduplicationId=deduplication_id,
            )

            message_id = response["MessageId"]
            print(f"DEBUG: Message sent successfully, MessageId: {message_id}")
            return message_id
        except ClientError as e:
            print(f"ERROR: Failed to send SQS message: {e}")
            raise RuntimeError(f"Failed to send message to SQS: {e}") from e

    def receive_messages(
        self, max_messages: int = 1, wait_time: int = 20
    ) -> list[dict]:
        """
        Receive messages from queue (for worker polling).

        Args:
            max_messages: Maximum messages to receive (1-10)
            wait_time: Long polling wait time in seconds

        Returns:
            List of message dicts

        Raises:
            ClientError: If SQS operation fails
        """
        try:
            print(f"DEBUG: Polling SQS queue: {self.queue_url}")
            print(f"DEBUG: MaxMessages={max_messages}, WaitTime={wait_time}s")

            response = self.sqs.receive_message(
                QueueUrl=self.queue_url,
                MaxNumberOfMessages=max_messages,
                WaitTimeSeconds=wait_time,
                AttributeNames=["All"],
            )

            messages = response.get("Messages", [])
            print(f"DEBUG: SQS response keys: {response.keys()}")
            print(f"DEBUG: Messages received: {len(messages)}")

            if messages:
                for i, msg in enumerate(messages):
                    print(f"DEBUG: Message {i+1} - MessageId: {msg.get('MessageId')}")
                    print(f"DEBUG: Message {i+1} - Body preview: {msg.get('Body', '')[:100]}...")

            return messages
        except ClientError as e:
            print(f"ERROR: SQS receive failed: {e}")
            raise RuntimeError(f"Failed to receive messages from SQS: {e}") from e

    def delete_message(self, receipt_handle: str) -> None:
        """
        Delete message from queue (after successful processing).

        Args:
            receipt_handle: Message receipt handle from receive_message

        Raises:
            ClientError: If SQS operation fails
        """
        try:
            self.sqs.delete_message(
                QueueUrl=self.queue_url, ReceiptHandle=receipt_handle
            )
        except ClientError as e:
            raise RuntimeError(f"Failed to delete message from SQS: {e}") from e

    def change_visibility_timeout(
        self, receipt_handle: str, timeout: int
    ) -> None:
        """
        Change message visibility timeout (for retry logic).

        Args:
            receipt_handle: Message receipt handle
            timeout: New visibility timeout in seconds

        Raises:
            ClientError: If SQS operation fails
        """
        try:
            self.sqs.change_message_visibility(
                QueueUrl=self.queue_url,
                ReceiptHandle=receipt_handle,
                VisibilityTimeout=timeout,
            )
        except ClientError as e:
            raise RuntimeError(
                f"Failed to change message visibility: {e}"
            ) from e
