"""
OpenAI兼容的Gemini视觉分析器
使用标准OpenAI格式调用Gemini代理服务
"""

import asyncio
import base64
import io
from pathlib import Path
from typing import List, Union

import PIL.Image
import requests
from loguru import logger
from tenacity import retry, stop_after_attempt, retry_if_exception_type, wait_exponential
from tqdm import tqdm


class GeminiOpenAIAnalyzer:
    """OpenAI兼容的Gemini视觉分析器类"""

    def __init__(self, model_name: str = "gemini-2.0-flash-exp", api_key: str = None, base_url: str = None):
        """初始化OpenAI兼容的Gemini分析器"""
        if not api_key:
            raise ValueError("必须提供API密钥")
        
        if not base_url:
            raise ValueError("必须提供OpenAI兼容的代理端点URL")

        self.model_name = model_name
        self.api_key = api_key
        self.base_url = base_url.rstrip('/')

        # 初始化OpenAI客户端
        self._configure_client()

    def _configure_client(self):
        """配置OpenAI兼容的客户端"""
        from openai import OpenAI
        self.client = OpenAI(
            api_key=self.api_key,
            base_url=self.base_url
        )
        logger.info(f"配置OpenAI兼容Gemini代理，端点: {self.base_url}, 模型: {self.model_name}")

    @retry(
        stop=stop_after_attempt(3),
        wait=wait_exponential(multiplier=1, min=4, max=10),
        retry=retry_if_exception_type((requests.exceptions.RequestException, Exception))
    )
    async def _generate_content_with_retry(self, prompt, batch):
        """使用重试机制调用OpenAI兼容的Gemini代理"""
        try:
            return await self._generate_with_openai_api(prompt, batch)
        except Exception as e:
            logger.warning(f"OpenAI兼容Gemini代理请求异常: {str(e)}")
            raise

    async def _generate_with_openai_api(self, prompt, batch):
        """使用OpenAI兼容接口生成内容"""
        # 将PIL图片转换为base64编码
        image_contents = []
        for img in batch:
            # 将PIL图片转换为字节流
            img_buffer = io.BytesIO()
            img.save(img_buffer, format='JPEG', quality=85)
            img_bytes = img_buffer.getvalue()
            
            # 转换为base64
            img_base64 = base64.b64encode(img_bytes).decode('utf-8')
            image_contents.append({
                "type": "image_url",
                "image_url": {
                    "url": f"data:image/jpeg;base64,{img_base64}"
                }
            })
        
        # 构建OpenAI格式的消息
        messages = [
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": prompt},
                    *image_contents
                ]
            }
        ]
        
        # 调用OpenAI兼容接口
        response = await asyncio.to_thread(
            self.client.chat.completions.create,
            model=self.model_name,
            messages=messages,
            max_tokens=4000,
            temperature=1.0
        )
        
        # 创建兼容的响应对象
        class CompatibleResponse:
            def __init__(self, text):
                self.text = text
        
        return CompatibleResponse(response.choices[0].message.content)

    async def analyze_images(self,
                           images: List[Union[str, Path, PIL.Image.Image]],
                           prompt: str,
                           batch_size: int = 10) -> List[str]:
        """
        分析图片并返回结果

        Args:
            images: 图片路径列表或PIL图片对象列表
            prompt: 分析提示词
            batch_size: 批处理大小

        Returns:
            分析结果列表
        """
        logger.info(f"开始分析 {len(images)} 张图片，使用OpenAI兼容Gemini代理")
        
        # 加载图片
        loaded_images = []
        for img in images:
            if isinstance(img, (str, Path)):
                try:
                    pil_img = PIL.Image.open(img)
                    # 调整图片大小以优化性能
                    if pil_img.size[0] > 1024 or pil_img.size[1] > 1024:
                        pil_img.thumbnail((1024, 1024), PIL.Image.Resampling.LANCZOS)
                    loaded_images.append(pil_img)
                except Exception as e:
                    logger.error(f"加载图片失败 {img}: {str(e)}")
                    continue
            elif isinstance(img, PIL.Image.Image):
                loaded_images.append(img)
            else:
                logger.warning(f"不支持的图片类型: {type(img)}")
                continue

        if not loaded_images:
            raise ValueError("没有有效的图片可以分析")

        # 分批处理
        results = []
        total_batches = (len(loaded_images) + batch_size - 1) // batch_size
        
        for i in tqdm(range(0, len(loaded_images), batch_size), 
                     desc="分析图片批次", total=total_batches):
            batch = loaded_images[i:i + batch_size]
            
            try:
                response = await self._generate_content_with_retry(prompt, batch)
                results.append(response.text)
                
                # 添加延迟以避免API限流
                if i + batch_size < len(loaded_images):
                    await asyncio.sleep(1)
                    
            except Exception as e:
                logger.error(f"分析批次 {i//batch_size + 1} 失败: {str(e)}")
                results.append(f"分析失败: {str(e)}")

        logger.info(f"完成图片分析，共处理 {len(results)} 个批次")
        return results

    def analyze_images_sync(self,
                           images: List[Union[str, Path, PIL.Image.Image]],
                           prompt: str,
                           batch_size: int = 10) -> List[str]:
        """
        同步版本的图片分析方法
        """
        return asyncio.run(self.analyze_images(images, prompt, batch_size))
