"""Gemini (Google) adapter using google-genai SDK."""

import math
import mimetypes
import time
from pathlib import Path
from typing import List, Optional

from google import genai
from google.genai import types

from .base import VendorAdapter
from ..models import Response, Usage


class GeminiAdapter(VendorAdapter):
    """
    Google Gemini adapter using official google-genai SDK.

    Supports:
    - Native multimodal via Files API
    - PDF, images, video, audio
    - Custom base_url for proxies
    - Configurable file cleanup and wait timeout
    """

    # Default model
    DEFAULT_MODEL = "gemini-2.5-flash"

    def __init__(
        self,
        api_key: str,
        model: Optional[str] = None,
        base_url: Optional[str] = None,
        timeout: Optional[float] = None,
        file_wait_timeout: float = 60,
        cleanup_files: bool = False,
        **kwargs
    ):
        """
        Initialize Gemini adapter.

        Args:
            api_key: Google API key.
            model: Model name. Defaults to gemini-2.5-flash.
            base_url: Custom API endpoint (for proxies).
            timeout: Request timeout in seconds.
            file_wait_timeout: Max seconds to wait for file processing. Default 60.
            cleanup_files: Whether to delete uploaded files after chat. Default False.
                          Files are uploaded to your Google Cloud account, set True
                          to auto-cleanup after each request.
            **kwargs: Additional options passed to base adapter.
        """
        super().__init__(
            api_key=api_key,
            model=model or self.DEFAULT_MODEL,
            base_url=base_url,
            timeout=timeout,
            **kwargs
        )

        self.file_wait_timeout = file_wait_timeout
        self.cleanup_files = cleanup_files

        # Initialize client
        client_kwargs = {"api_key": self.api_key}
        if self.base_url or self.timeout:
            http_options = {}
            if self.base_url:
                http_options["base_url"] = self.base_url
            if self.timeout:
                # Use math.ceil to avoid losing precision (e.g., 0.5 -> 1, not 0)
                http_options["timeout"] = math.ceil(self.timeout)
            client_kwargs["http_options"] = types.HttpOptions(**http_options)

        self.client = genai.Client(**client_kwargs)

    def _upload_file_obj(self, file_path: Path):
        """Upload file to Gemini Files API and return the File object."""
        path = self._validate_file(file_path)
        mime_type = mimetypes.guess_type(str(path))[0] or "application/octet-stream"

        # 透明桥接：直接调用 SDK，让原始异常透传
        with open(path, "rb") as f:
            uploaded = self.client.files.upload(
                file=f,
                config=types.UploadFileConfig(
                    display_name=path.name,
                    mime_type=mime_type
                )
            )

        # Wait for file to be processed (with configurable timeout)
        start_time = time.time()
        last_state = getattr(getattr(uploaded, "state", None), "name", "UNKNOWN")
        while getattr(getattr(uploaded, "state", None), "name", None) == "PROCESSING":
            elapsed = time.time() - start_time
            if elapsed > self.file_wait_timeout:
                raise RuntimeError(
                    f"Gemini file processing timed out after {self.file_wait_timeout}s "
                    f"for '{path}' (file={getattr(uploaded, 'name', None)}, last_state={last_state}). "
                    f"Consider increasing file_wait_timeout."
                )
            time.sleep(1)
            # 透明桥接：状态轮询失败让 SDK 原始异常透传
            uploaded = self.client.files.get(name=uploaded.name)
            last_state = getattr(getattr(uploaded, "state", None), "name", "UNKNOWN")

        final_state = getattr(getattr(uploaded, "state", None), "name", "UNKNOWN")
        if final_state != "ACTIVE":
            raise RuntimeError(
                f"Gemini file upload failed for '{path}' "
                f"(file={getattr(uploaded, 'name', None)}, state={final_state})"
            )

        return uploaded

    def upload_file(self, file_path: Path) -> str:
        """
        Upload file to Gemini Files API.

        Returns:
            File name (e.g., "files/xxx") for referencing in chat or later operations.
        """
        return self._upload_file_obj(file_path).name

    def _delete_file_by_name(self, file_name: str) -> None:
        """Delete an uploaded file from Gemini Files API by name."""
        import logging
        logger = logging.getLogger(__name__)
        try:
            self.client.files.delete(name=file_name)
            logger.debug(f"Successfully deleted Gemini file: {file_name}")
        except Exception as e:
            # Log but don't interrupt flow - cleanup failure is non-critical
            logger.warning(f"Failed to cleanup Gemini file {file_name}: {e}")

    def chat(
        self,
        prompt: str,
        files: Optional[List[Path]] = None,
        **kwargs
    ) -> Response:
        """
        Send chat request to Gemini.

        Supports multimodal input via Files API.

        Args:
            prompt: User prompt text.
            files: Optional list of file paths to upload.
            **kwargs: Additional parameters (temperature, max_output_tokens, etc.)

        Returns:
            Response with content, usage, and raw response.
        """
        contents = []

        # Upload and add files
        uploaded_file_names: List[str] = []
        if files:
            for file_path in files:
                file_obj = self._upload_file_obj(Path(file_path))
                uploaded_file_names.append(file_obj.name)
                contents.append(file_obj)

        # Add text prompt
        contents.append(prompt)

        # Build config - 透传所有参数，让 SDK 自行校验
        # 支持的参数包括：temperature, max_output_tokens, system_instruction,
        # response_mime_type, safety_settings, thinking_config 等
        config_args = kwargs

        try:
            # Send request
            response = self.client.models.generate_content(
                model=self.model,
                contents=contents,
                config=types.GenerateContentConfig(**config_args)
            )

            # 透明桥接：直接透传 SDK 返回的原始内容
            # 包括被安全过滤、重复过滤等情况，都不做拦截和替换
            try:
                content = response.text or ""
            except (ValueError, AttributeError):
                # SDK 在某些情况下（如安全过滤）访问 .text 会抛 ValueError
                # 此时透传原始响应的字符串表示，让调用方看到真实状态
                content = str(response) if response else ""

            return Response(
                content=content,
                usage=Usage.from_gemini(getattr(response, "usage_metadata", None)),
                raw=response
            )

        finally:
            # Cleanup uploaded files if requested
            if self.cleanup_files:
                for file_name in uploaded_file_names:
                    self._delete_file_by_name(file_name)
