"""Sinhala MCP Server - Production-ready server implementation.

This server translates Sinhala/Singlish instructions into English technical prompts
using Google Gemini AI via the modern google-genai SDK.
"""

import asyncio
import logging
import os
import sys
from datetime import datetime
from typing import Any

# Configure structured logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger("sinhala-mcp")

# Modern Google GenAI SDK (GA as of May 2025)
from google import genai
from google.genai import types
from google.api_core.exceptions import (
    InvalidArgument,
    NotFound,
    PermissionDenied,
    ResourceExhausted,
)

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent

# Configuration
MAX_INSTRUCTION_LENGTH = 5000
API_TIMEOUT_SECONDS = 30
MAX_RETRIES = 2
RETRY_DELAY_SECONDS = 1
DEFAULT_MODEL = "gemini-2.0-flash-exp"

# System prompt for translation
TRANSLATION_SYSTEM_PROMPT = """Act as a Senior Technical Product Manager. Translate this Sinhala/Singlish input into a precise, step-by-step English technical specification for an AI coding agent.

Rules:
- Infer technical context (e.g., "Login" → authentication flow, "database" → data storage layer)
- Output ONLY the technical prompt, no explanations
- Be specific and actionable
- Use professional technical terminology
- Keep it concise but complete

Example:
Input: "mama dashboard ekak hadanna one"
Output: "Create a data dashboard with metrics visualization, filtering capabilities, and responsive layout. Include authentication and user-specific data views."
"""

# Create MCP server instance
server = Server("sinhala-mcp")


class SinhalaTranslationError(Exception):
    """Custom exception for translation errors."""

    pass


def validate_instruction(instruction: str) -> tuple[bool, str | None]:
    """Validate user input instruction.

    Args:
        instruction: The instruction text to validate

    Returns:
        Tuple of (is_valid, error_message)
    """
    if not instruction or not instruction.strip():
        return False, "Instruction cannot be empty"

    if len(instruction) > MAX_INSTRUCTION_LENGTH:
        return False, f"Instruction too long (max {MAX_INSTRUCTION_LENGTH} characters)"

    # Check for potential injection attempts
    dangerous_patterns = ["<script>", "javascript:", "onerror=", "onload="]
    instruction_lower = instruction.lower()
    for pattern in dangerous_patterns:
        if pattern in instruction_lower:
            return False, f"Instruction contains potentially harmful content: {pattern}"

    return True, None


async def translate_with_gemini(
    client: genai.Client,
    instruction: str,
    model: str = DEFAULT_MODEL,
) -> str:
    """Translate instruction using Gemini AI with retry logic.

    Args:
        client: Google GenAI client
        instruction: Sinhala/Singlish instruction to translate
        model: Gemini model to use

    Returns:
        Translated English technical prompt

    Raises:
        SinhalaTranslationError: If translation fails after retries
    """
    last_error = None

    for attempt in range(MAX_RETRIES + 1):
        try:
            logger.info(f"Translation attempt {attempt + 1}/{MAX_RETRIES + 1}")

            # Configure generation with safety settings
            config = types.GenerateContentConfig(
                system_instruction=TRANSLATION_SYSTEM_PROMPT,
                temperature=0.7,
                max_output_tokens=1000,
                safety_settings=[
                    types.SafetySetting(
                        category="HARM_CATEGORY_HARASSMENT",
                        threshold="BLOCK_MEDIUM_AND_ABOVE",
                    ),
                    types.SafetySetting(
                        category="HARM_CATEGORY_HATE_SPEECH",
                        threshold="BLOCK_MEDIUM_AND_ABOVE",
                    ),
                ],
            )

            # Generate content with timeout
            response = await asyncio.wait_for(
                client.aio.models.generate_content(
                    model=model,
                    contents=instruction,
                    config=config,
                ),
                timeout=API_TIMEOUT_SECONDS,
            )

            # Extract and validate response
            if not response.candidates or not response.candidates[0].content:
                raise SinhalaTranslationError("Empty response from Gemini API")

            translated_text = response.candidates[0].content.parts[0].text.strip()

            if not translated_text:
                raise SinhalaTranslationError("Received empty translation")

            logger.info("Translation successful")
            return translated_text

        except asyncio.TimeoutError:
            last_error = f"API timeout after {API_TIMEOUT_SECONDS} seconds"
            logger.warning(f"Attempt {attempt + 1}: {last_error}")

        except InvalidArgument as e:
            # Invalid arguments - don't retry
            raise SinhalaTranslationError(f"Invalid API request: {e}")

        except (PermissionDenied, NotFound) as e:
            # Auth/API key issues - don't retry
            raise SinhalaTranslationError(f"API authentication error: {e}")

        except ResourceExhausted as e:
            # Rate limit - retry with delay
            last_error = f"Rate limit exceeded: {e}"
            logger.warning(f"Attempt {attempt + 1}: {last_error}")

        except Exception as e:
            last_error = f"Unexpected error: {e}"
            logger.error(f"Attempt {attempt + 1}: {last_error}")

        # Retry delay for non-fatal errors
        if attempt < MAX_RETRIES:
            await asyncio.sleep(RETRY_DELAY_SECONDS * (attempt + 1))

    raise SinhalaTranslationError(f"Translation failed after {MAX_RETRIES + 1} attempts: {last_error}")


@server.list_tools()
async def list_tools() -> list[Tool]:
    """List available MCP tools.

    Returns:
        A list of available tools.
    """
    return [
        Tool(
            name="translate_sinhala_instruction",
            description="Translate a Sinhala or Singlish instruction into a precise English technical prompt for an AI coding agent. Automatically infers technical context.",
            inputSchema={
                "type": "object",
                "properties": {
                    "instruction": {
                        "type": "string",
                        "description": f"The Sinhala or Singlish instruction to translate (max {MAX_INSTRUCTION_LENGTH} characters).",
                        "maxLength": MAX_INSTRUCTION_LENGTH,
                    }
                },
                "required": ["instruction"],
            },
        ),
        Tool(
            name="health_check",
            description="Check if the MCP server and Gemini API connection are working.",
            inputSchema={
                "type": "object",
                "properties": {},
                "required": [],
            },
        ),
    ]


@server.call_tool()
async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
    """Handle tool calls.

    Args:
        name: The name of the tool being called.
        arguments: The arguments passed to the tool.

    Returns:
        A list of text content responses.
    """
    start_time = datetime.now()

    if name == "translate_sinhala_instruction":
        instruction = arguments.get("instruction", "")

        # Validate input
        is_valid, error_msg = validate_instruction(instruction)
        if not is_valid:
            logger.warning(f"Invalid instruction: {error_msg}")
            return [
                TextContent(
                    type="text",
                    text=f"Error: {error_msg}",
                )
            ]

        # Check API key
        api_key = os.environ.get("GEMINI_API_KEY")
        if not api_key:
            logger.error("GEMINI_API_KEY not found in environment")
            return [
                TextContent(
                    type="text",
                    text="Error: GEMINI_API_KEY not configured. Please set it in your MCP client settings.\n\n"
                    "Configuration instructions:\n"
                    "1. Get your API key from: https://makersuite.google.com/app/apikey\n"
                    "2. Add to your MCP client config under 'env':\n"
                    "   {\n"
                    "     \"env\": {\n"
                    "       \"GEMINI_API_KEY\": \"your-api-key-here\"\n"
                    "     }\n"
                    "   }",
                )
            ]

        try:
            # Initialize GenAI client
            client = genai.Client(api_key=api_key)

            # Translate instruction
            translated_text = await translate_with_gemini(client, instruction)

            # Log success
            elapsed = (datetime.now() - start_time).total_seconds()
            logger.info(f"Translation completed in {elapsed:.2f}s")

            return [
                TextContent(
                    type="text",
                    text=f"Original (Sinhala/Singlish):\n{instruction}\n\nTranslated (English Technical Prompt):\n{translated_text}",
                )
            ]

        except SinhalaTranslationError as e:
            logger.error(f"Translation error: {e}")
            return [
                TextContent(
                    type="text",
                    text=f"Translation Error: {str(e)}\n\n"
                    f"Please check your GEMINI_API_KEY and try again.",
                )
            ]

        except Exception as e:
            logger.exception(f"Unexpected error during translation")
            return [
                TextContent(
                    type="text",
                    text=f"Unexpected Error: {str(e)}\n\n"
                    f"Please try again or contact support if the issue persists.",
                )
            ]

    elif name == "health_check":
        """Health check endpoint."""
        api_key = os.environ.get("GEMINI_API_KEY")

        if not api_key:
            return [
                TextContent(
                    type="text",
                    text="Health Check: FAILED - GEMINI_API_KEY not configured",
                )
            ]

        try:
            # Test API connection
            client = genai.Client(api_key=api_key)
            # Simple test with minimal request
            await asyncio.wait_for(
                client.aio.models.generate_content(
                    model=DEFAULT_MODEL,
                    contents="test",
                ),
                timeout=5.0,
            )

            return [
                TextContent(
                    type="text",
                    text=f"Health Check: PASSED\n"
                    f"Server: sinhala-mcp v0.1.0\n"
                    f"API Connection: Active\n"
                    f"Timestamp: {datetime.now().isoformat()}",
                )
            ]

        except Exception as e:
            return [
                TextContent(
                    type="text",
                    text=f"Health Check: FAILED - {str(e)}",
                )
            ]

    else:
        logger.warning(f"Unknown tool called: {name}")
        return [TextContent(type="text", text=f"Error: Unknown tool '{name}'")]


def main():
    """Entry point for the sinhala-mcp CLI command."""
    logger.info("Starting sinhala-mcp server v0.1.0")

    async def run_server():
        try:
            async with stdio_server() as (read_stream, write_stream):
                await server.run(
                    read_stream,
                    write_stream,
                    server.create_initialization_options(),
                )
        except Exception as e:
            logger.exception("Server error")
            sys.exit(1)

    asyncio.run(run_server())


if __name__ == "__main__":
    main()
