"""
Anthropic-specific batch processing implementation.

This module contains the Anthropic batch processing provider class.
"""

import json
from typing import Any, Optional, Union
import io
import logging
from .base import BatchProvider
from ..models import BatchJobInfo

logger = logging.getLogger(__name__)


class AnthropicProvider(BatchProvider):
    """Anthropic batch processing provider"""

    def submit_batch(
        self,
        file_path_or_buffer: Union[str, io.BytesIO],
        metadata: Optional[dict[str, Any]] = None,
        **kwargs,
    ) -> str:
        """Submit Anthropic batch job"""
        _ = kwargs  # Unused but accepted for API consistency
        try:
            import anthropic

            client = anthropic.Anthropic()

            # Note: Anthropic doesn't support metadata in batch creation
            # but we accept it for API consistency
            if metadata:
                print(
                    f"Note: Anthropic batches don't support metadata. Ignoring: {metadata}"
                )

            # TODO(#batch-api-stable): Remove beta fallback when stable API is available
            try:
                batches_client = client.messages.batches
            except AttributeError:
                batches_client = client.beta.messages.batches

            if isinstance(file_path_or_buffer, str):
                with open(file_path_or_buffer) as f:
                    requests = [json.loads(line) for line in f if line.strip()]
            elif isinstance(file_path_or_buffer, io.BytesIO):
                file_path_or_buffer.seek(0)
                content = file_path_or_buffer.read().decode("utf-8")
                requests = [
                    json.loads(line) for line in content.split("\n") if line.strip()
                ]
            else:
                raise ValueError(
                    f"Unsupported file_path_or_buffer type: {type(file_path_or_buffer)}"
                )

            batch = batches_client.create(requests=requests)
            return batch.id
        except (ValueError, TypeError) as e:
            # Re-raise validation errors as-is
            logger.error(f"Validation error in Anthropic batch submission: {e}")
            raise
        except Exception as e:
            raise RuntimeError(f"Failed to submit Anthropic batch: {e}") from e

    def get_status(self, batch_id: str) -> dict[str, Any]:
        """Get Anthropic batch status"""
        try:
            import anthropic

            client = anthropic.Anthropic()

            # TODO(#batch-api-stable): Remove beta fallback when stable API is available
            try:
                batches_client = client.messages.batches
            except AttributeError:
                batches_client = client.beta.messages.batches

            batch = batches_client.retrieve(batch_id)
            return {
                "id": batch.id,
                "status": batch.processing_status,
                "created_at": batch.created_at,
                "request_counts": getattr(batch, "request_counts", {}),
            }
        except Exception as e:
            raise Exception(f"Failed to get Anthropic batch status: {e}") from e

    def retrieve_results(self, batch_id: str) -> str:
        """Retrieve Anthropic batch results"""
        try:
            import anthropic

            client = anthropic.Anthropic()

            # TODO(#batch-api-stable): Remove beta fallback when stable API is available
            try:
                batches_client = client.messages.batches
            except AttributeError:
                batches_client = client.beta.messages.batches

            batch = batches_client.retrieve(batch_id)

            # Check for various terminal states
            if batch.processing_status in ["failed", "cancelled", "expired"]:
                raise Exception(
                    f"Batch job failed with status: {batch.processing_status}"
                )

            if batch.processing_status != "ended":
                raise Exception(
                    f"Batch not completed, status: {batch.processing_status}"
                )

            # Check if all requests failed
            request_counts = getattr(batch, "request_counts", None)
            if request_counts:
                succeeded = getattr(request_counts, "succeeded", 0)
                errored = getattr(request_counts, "errored", 0)
                total = getattr(request_counts, "total", 0)

                if errored > 0 and succeeded == 0:
                    raise RuntimeError(
                        f"All {total} batch requests failed. No results will be available."
                    )

            results = batches_client.results(batch_id)
            results_lines = []
            for result in results:
                results_lines.append(result.model_dump_json())

            return "\n".join(results_lines)
        except Exception as e:
            raise Exception(f"Failed to retrieve Anthropic results: {e}") from e

    def download_results(self, batch_id: str, file_path: str) -> None:
        """Download Anthropic batch results to a file"""
        try:
            import anthropic

            client = anthropic.Anthropic()

            # TODO(#batch-api-stable): Remove beta fallback when stable API is available
            try:
                batches_client = client.messages.batches
            except AttributeError:
                batches_client = client.beta.messages.batches

            batch = batches_client.retrieve(batch_id)

            # Check for various terminal states
            if batch.processing_status in ["failed", "cancelled", "expired"]:
                raise Exception(
                    f"Batch job failed with status: {batch.processing_status}"
                )

            if batch.processing_status != "ended":
                raise Exception(
                    f"Batch not completed, status: {batch.processing_status}"
                )

            # Check if all requests failed
            request_counts = getattr(batch, "request_counts", None)
            if request_counts:
                succeeded = getattr(request_counts, "succeeded", 0)
                errored = getattr(request_counts, "errored", 0)
                total = getattr(request_counts, "total", 0)

                if errored > 0 and succeeded == 0:
                    raise RuntimeError(
                        f"All {total} batch requests failed. No results will be available."
                    )

            results = batches_client.results(batch_id)
            with open(file_path, "w") as f:
                for result in results:
                    f.write(result.model_dump_json() + "\n")
        except Exception as e:
            raise Exception(f"Failed to download Anthropic results: {e}") from e

    def cancel_batch(self, batch_id: str) -> dict[str, Any]:
        """Cancel Anthropic batch job"""
        try:
            import anthropic

            client = anthropic.Anthropic()

            # TODO(#batch-api-stable): Remove beta fallback when stable API is available
            try:
                batches_client = client.messages.batches
            except AttributeError:
                batches_client = client.beta.messages.batches

            batch = batches_client.cancel(batch_id)
            return batch.model_dump()
        except Exception as e:
            raise Exception(f"Failed to cancel Anthropic batch: {e}") from e

    def delete_batch(self, batch_id: str) -> dict[str, Any]:
        """Delete Anthropic batch job"""
        try:
            import anthropic

            client = anthropic.Anthropic()

            # TODO(#batch-api-stable): Remove beta fallback when stable API is available
            try:
                batches_client = client.messages.batches
            except AttributeError:
                batches_client = client.beta.messages.batches

            batch = batches_client.retrieve(batch_id)
            return {
                "id": batch.id,
                "status": batch.processing_status,
                "message": "Anthropic does not support batch deletion",
            }
        except Exception as e:
            raise Exception(f"Failed to delete Anthropic batch: {e}") from e

    def list_batches(self, limit: int = 10) -> list[BatchJobInfo]:
        """List Anthropic batch jobs"""
        try:
            import anthropic

            client = anthropic.Anthropic()

            # TODO(#batch-api-stable): Remove beta fallback when stable API is available
            try:
                batches_client = client.messages.batches
            except AttributeError:
                batches_client = client.beta.messages.batches

            batches = batches_client.list(limit=limit)
            return [
                BatchJobInfo.from_anthropic(batch.model_dump())
                for batch in batches.data
            ]
        except Exception as e:
            raise Exception(f"Failed to list Anthropic batches: {e}") from e
