# -*- coding: utf-8 -*-
"""
Response API formatter implementation.
Handles formatting for OpenAI Response API format with multimodal support.
"""

from __future__ import annotations

from typing import Any, Dict, List

from ._formatter_base import FormatterBase


class ResponseFormatter(FormatterBase):
    """Formatter for Response API format with multimodal support."""

    def format_messages(self, messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        Convert messages from Chat Completions format to Response API format.

        Chat Completions tool message: {"role": "tool", "tool_call_id": "...", "content": "..."}
        Response API tool message: {"type": "function_call_output", "call_id": "...", "output": "..."}

        Also handles multimodal content conversion:
        - {"type": "text", "text": "..."} → {"type": "input_text", "text": "..."}
        - {"type": "image", "url": "..."} → {"type": "input_image", "image_url": "..."}
        - {"type": "image", "base64": "..."} → {"type": "input_image", "image_url": "data:image/...;base64,..."}

        Note: Assistant messages with tool_calls should not be in input - they're generated by the backend.
        """
        cleaned_messages = []
        for message in messages:
            if "status" in message and "role" not in message:
                # Create a copy without 'status'
                cleaned_message = {k: v for k, v in message.items() if k != "status"}
                cleaned_messages.append(cleaned_message)
            else:
                cleaned_messages.append(message)

        converted_messages = []

        for message in cleaned_messages:
            if message.get("role") == "tool":
                # Convert Chat Completions tool message to Response API format
                converted_message = {
                    "type": "function_call_output",
                    "call_id": message.get("tool_call_id"),
                    "output": message.get("content", ""),
                }
                converted_messages.append(converted_message)
            elif message.get("type") == "function_call_output":
                # Already in Response API format
                converted_messages.append(message)
            elif message.get("role") == "assistant" and "tool_calls" in message:
                # Assistant message with tool_calls - remove tool_calls when sending as input
                cleaned_message = {k: v for k, v in message.items() if k != "tool_calls"}
                converted_messages.append(cleaned_message)
            else:
                # For other message types, check for multimodal content
                converted_message = self._convert_multimodal_content(message.copy())
                converted_messages.append(converted_message)

        return converted_messages

    def _convert_multimodal_content(self, message: Dict[str, Any]) -> Dict[str, Any]:
        """
        Convert multimodal content to Response API format.

        Handles conversion of content arrays with text and image items:
        - text items: {"type": "text", "text": "..."} → {"type": "input_text", "text": "..."}
        - image URL: {"type": "image", "url": "..."} → {"type": "input_image", "image_url": "..."}
        - image base64: {"type": "image", "base64": "...", "mime_type": "..."} →
                        {"type": "input_image", "image_url": "data:image/...;base64,..."}
        - file: {"type": "file", "file_id": "..."} → {"type": "input_file", "file_id": "..."}

        Args:
            message: Message dictionary that may contain multimodal content

        Returns:
            Message with content converted to Response API format
        """
        content = message.get("content")

        # If content is not a list, no conversion needed
        if not isinstance(content, list):
            return message

        converted_content = []
        for item in content:
            if not isinstance(item, dict):
                # If item is a string, treat as text
                converted_content.append({"type": "input_text", "text": str(item)})
                continue

            item_type = item.get("type")

            if item_type == "text":
                # Convert text item to input_text
                converted_content.append(
                    {
                        "type": "input_text",
                        "text": item.get("text", ""),
                    },
                )

            elif item_type == "image":
                # Convert image item to input_image
                converted_item = self._convert_image_content(item)
                if converted_item:
                    converted_content.append(converted_item)

            elif item_type == "file":
                # Convert file item to input_file
                converted_content.append(
                    {
                        "type": "input_file",
                        "file_id": item.get("file_id", ""),
                    },
                )

            elif item_type == "file_pending_upload":
                converted_content.append(item)

            elif item_type in ["input_text", "input_image", "input_file"]:
                # Already in Response API format
                converted_content.append(item)

            else:
                # Unknown type, pass through
                converted_content.append(item)

        message["content"] = converted_content
        return message

    def _convert_image_content(self, image_item: Dict[str, Any]) -> Dict[str, Any]:
        """
        Convert image content item to Response API format.

        Supports:
        - URL format: {"type": "image", "url": "https://..."}
        - Base64 format: {"type": "image", "base64": "...", "mime_type": "image/jpeg"}
        - Image URL format: {"type": "image", "image_url": "..."} (already correct)

        Args:
            image_item: Image content item dictionary

        Returns:
            Converted image item in Response API format, or None if invalid
        """
        # Check if already in correct format
        if "image_url" in image_item:
            return {
                "type": "input_image",
                "image_url": image_item["image_url"],
            }

        # Handle URL format
        if "url" in image_item:
            return {
                "type": "input_image",
                "image_url": image_item["url"],
            }

        # Handle base64 format
        if "base64" in image_item:
            mime_type = image_item.get("mime_type", "image/jpeg")
            base64_data = image_item["base64"]

            # Validate base64 data
            if not self._validate_base64_image(base64_data):
                return None

            # Create data URL
            data_url = f"data:{mime_type};base64,{base64_data}"
            return {
                "type": "input_image",
                "image_url": data_url,
            }

        # No valid image data found
        return None

    def _validate_base64_image(self, base64_data: str) -> bool:
        """
        Validate base64 image data.

        Checks:
        - Data is not empty
        - Data is valid base64 (basic check)
        - Data size is within limits (20MB)

        Args:
            base64_data: Base64 encoded image string

        Returns:
            True if valid, False otherwise
        """
        if not base64_data:
            return False

        # Check size (base64 is ~33% larger than binary)
        # 20MB binary = ~27MB base64
        max_base64_size = 27 * 1024 * 1024
        if len(base64_data) > max_base64_size:
            return False

        # Basic base64 validation (contains only valid characters)
        import re

        if not re.match(r"^[A-Za-z0-9+/]*={0,2}$", base64_data):
            return False

        return True

    def format_tools(self, tools: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        Convert tools from Chat Completions format to Response API format if needed.

        Chat Completions format: {"type": "function", "function": {"name": ..., "description": ..., "parameters": ...}}
        Response API format: {"type": "function", "name": ..., "description": ..., "parameters": ...}
        """
        if not tools:
            return tools

        converted_tools = []
        for tool in tools:
            if tool.get("type") == "function" and "function" in tool:
                # Chat Completions format - convert to Response API format
                func = tool["function"]
                converted_tools.append(
                    {
                        "type": "function",
                        "name": func["name"],
                        "description": func["description"],
                        "parameters": func.get("parameters", {}),
                    },
                )
            else:
                # Already in Response API format or non-function tool
                converted_tools.append(tool)

        return converted_tools

    def format_mcp_tools(self, mcp_functions: Dict[str, Any]) -> List[Dict[str, Any]]:
        """Convert MCP tools to Response API format (OpenAI function declarations)."""
        if not mcp_functions:
            return []

        converted_tools = []
        for mcp_function in mcp_functions.values():
            if hasattr(mcp_function, "to_openai_format"):
                tool = mcp_function.to_openai_format()
            else:
                # Fallback format - Response API expects flat structure
                tool = {
                    "type": "function",
                    "name": getattr(mcp_function, "name", "unknown"),
                    "description": getattr(mcp_function, "description", ""),
                    "parameters": getattr(mcp_function, "input_schema", {}),
                }
            converted_tools.append(tool)

        return converted_tools
