"""图片文件解析器，使用 Vision API 识别图片内容"""

import base64
import os
from typing import List, Optional

from api_client import ApiClient, EXTENSION_MIME_MAP
from exceptions import ApiError, ParseError
from parsers.base import BaseParser

DEFAULT_VISION_PROMPT = """\
请识别并提取图片中的所有文字和关键信息。请按以下结构输出：

1. **产品/主题名称**：图片展示的主要产品或主题
2. **文字内容**：图片中所有可见的文字，保持原始排版
3. **关键信息**：成分、功效、用法用量、规格、价格等结构化信息
4. **图片描述**：简要描述图片的视觉内容（产品外观、包装等）

如果某项信息不存在，可以省略该项。"""


class ImageParser(BaseParser):
    """图片解析器，通过 Vision API 将图片转换为文本描述"""

    def __init__(self, api_client: ApiClient, vision_prompt: Optional[str] = None):
        self._api_client = api_client
        self._vision_prompt = vision_prompt or DEFAULT_VISION_PROMPT

    def supported_extensions(self) -> List[str]:
        return [".png", ".jpg", ".jpeg", ".bmp", ".gif", ".webp"]

    def parse(self, file_path: str) -> str:
        """
        解析图片文件：读取二进制 → base64 编码 → 调用 Vision API → 返回文本描述。

        会将文件名作为上下文提示传入 prompt，提高识别准确度。
        """
        file_name = os.path.basename(file_path)
        product_name = os.path.splitext(file_name)[0]

        # 1. 读取图片文件
        try:
            with open(file_path, "rb") as f:
                image_bytes = f.read()
        except Exception as e:
            raise ParseError(file_name, f"文件读取失败: {e}")

        # 2. Base64 编码
        image_base64 = base64.b64encode(image_bytes).decode("utf-8")

        # 3. 根据扩展名确定 MIME 类型
        ext = os.path.splitext(file_path)[1].lower()
        mime_type = EXTENSION_MIME_MAP.get(ext, "image/png")

        # 4. 构建带文件名上下文的 prompt
        context_prompt = (
            f"{self._vision_prompt}\n\n"
            f"参考信息：该图片的文件名为「{product_name}」，可能与图片内容相关。"
        )

        # 5. 调用 Vision API
        try:
            result = self._api_client.vision(
                system_prompt=context_prompt,
                image_base64=image_base64,
                mime_type=mime_type,
            )
        except ApiError as e:
            raise ParseError(file_name, f"Vision API 调用失败: {e}")

        return result
