#!/usr/bin/env python3
"""
Step 3.1B: 使用多模态大模型生成 SVG 矢量图

根据精准描述 JSON，调用多模态 LLM 生成 SVG 代码
"""

import json
import argparse
import re
import sys
from pathlib import Path

# 配置
DEFAULT_CONFIG_PATH = "config.json"
DEFAULT_WIDTH = 1000


def load_config(config_path: str) -> dict:
    """加载配置文件"""
    with open(config_path, 'r', encoding='utf-8') as f:
        return json.load(f)


def load_description(description_path: str) -> dict:
    """加载插图描述 JSON"""
    with open(description_path, 'r', encoding='utf-8') as f:
        data = json.load(f)
    
    # 兼容不同格式：直接是描述 或 包含 target_description 的结构
    if 'target_description' in data:
        return data['target_description']
    return data


def build_svg_prompt(description: dict, width: int = 1000, icon_map: dict = None, review_data: dict = None) -> str:
    """构建 SVG 生成 Prompt"""

    overview = description.get('overview', '')
    diagram_type = description.get('diagram_type', 'flowchart')
    elements = description.get('elements', [])
    connections = description.get('connections', [])
    color_scheme = description.get('color_scheme', {})
    layout = description.get('layout', {})

    # 构建元素描述
    elements_desc = []
    for elem in elements:
        # [图标功能已注释] 将 icon/mixed 类型改为 text，避免生成 <image> 标签
        content_type = elem.get('content_type', 'text')
        if content_type in ('icon', 'mixed'):
            content_type = 'text'
        
        elem_info = {
            'id': elem.get('id', ''),
            'name': elem.get('name', ''),
            'shape': elem.get('shape', 'rectangle'),
            'color': elem.get('color', '#E8F4FD'),
            'position': elem.get('position', 'center'),
            'size': elem.get('size', 'medium'),
            'content_type': content_type,
            'icon_description': '',  # [图标功能已注释]
        }
        elements_desc.append(elem_info)

    # 构建连接描述
    connections_desc = []
    for conn in connections:
        conn_info = {
            'from': conn.get('from', ''),
            'to': conn.get('to', ''),
            'label': conn.get('label', ''),
            'style': conn.get('style', 'solid'),
            'arrow': conn.get('arrow', 'forward'),
            'color': conn.get('color', '#333333'),
        }
        connections_desc.append(conn_info)

    # [图标功能已注释] 构建图标引用说明
    # favicon_section = ""
    # if icon_map:
    #     favicon_lines = ["- Icon Elements (use <image> tag, will be embedded with actual image data):"]
    #     for elem in elements:
    #         elem_id = elem.get('id', '')
    #         if elem_id in icon_map:
    #             elem_name = elem.get('name', '')
    #             icon_desc = elem.get('icon_description', '')
    #             favicon_lines.append(f"  - {elem_name} (ID: {elem_id}): icon placeholder - {icon_desc}")
    #     favicon_section = "\n" + "\n".join(favicon_lines)
    favicon_section = ""
    
    # 处理 layout（可能是字符串或 dict）
    if isinstance(layout, str):
        layout_direction = layout
    else:
        layout_direction = layout.get('direction', 'left to right') if isinstance(layout, dict) else 'left to right'
    
    # 构建提示词
    prompt = _build_prompt_base(
        overview, diagram_type, width, elements_desc, connections_desc, 
        color_scheme, layout_direction, favicon_section, ""
    )
    
    return prompt


def build_svg_prompt_with_review(description: dict, width: int = 1000, icon_map: dict = None, review_data: dict = None) -> str:
    """构建带 review 的 SVG 生成 Prompt（读取原 SVG 内容）"""

    overview = description.get('overview', '')
    diagram_type = description.get('diagram_type', 'flowchart')
    elements = description.get('elements', [])
    connections = description.get('connections', [])
    color_scheme = description.get('color_scheme', {})
    layout = description.get('layout', {})

    # 构建元素描述
    elements_desc = []
    for elem in elements:
        content_type = elem.get('content_type', 'text')
        if content_type in ('icon', 'mixed'):
            content_type = 'text'
        
        elem_info = {
            'id': elem.get('id', ''),
            'name': elem.get('name', ''),
            'shape': elem.get('shape', 'rectangle'),
            'color': elem.get('color', '#E8F4FD'),
            'position': elem.get('position', 'center'),
            'size': elem.get('size', 'medium'),
            'content_type': content_type,
            'icon_description': '',
        }
        elements_desc.append(elem_info)

    # 构建连接描述
    connections_desc = []
    for conn in connections:
        conn_info = {
            'from': conn.get('from', ''),
            'to': conn.get('to', ''),
            'label': conn.get('label', ''),
            'style': conn.get('style', 'solid'),
            'arrow': conn.get('arrow', 'forward'),
            'color': conn.get('color', '#333333'),
        }
        connections_desc.append(conn_info)

    favicon_section = ""
    
    # 构建 review 部分
    review_section = ""
    if review_data:
        issues = review_data.get('issues', [])
        summary = review_data.get('summary', '')
        score = review_data.get('overall_score', '')
        source_svg = review_data.get('source_svg', '')
        source_desc = review_data.get('source_desc', '')
        source_svg_content = ""
        
        # 读取原 SVG 文件内容（完整读取）
        if source_svg and Path(source_svg).exists():
            try:
                with open(source_svg, 'r', encoding='utf-8') as f:
                    source_svg_content = f.read()
            except Exception as e:
                print(f"[警告] 读取原 SVG 失败: {e}", flush=True)
        
        if issues or summary:
            review_lines = [
                "",
                "## ===== PREVIOUS VERSION REVIEW =====",
                "This is an ITERATION - Please fix the issues from the previous SVG version below.",
            ]
            if source_svg:
                review_lines.append(f"- Previous version source file: {source_svg}")
            if source_desc:
                review_lines.append(f"- Previous version description file: {source_desc}")
            if score:
                review_lines.append(f"- Previous version overall score: {score}/10")
            
            if source_svg_content:
                review_lines.append("")
                review_lines.append("## Previous SVG Code (for reference):")
                review_lines.append(f"```svg\n{source_svg_content}\n```")
            
            if summary:
                review_lines.append(f"- Previous version summary: {summary}")
            
            if issues:
                review_lines.append("")
                review_lines.append("CRITICAL ISSUES TO FIX (based on previous SVG):")
                for issue in issues:
                    criterion = issue.get('criterion', '')
                    desc = issue.get('description', '')
                    suggestion = issue.get('suggestion', '')
                    review_lines.append(f"  * Criterion {criterion}: {desc}")
                    if suggestion:
                        review_lines.append(f"    → Action required: {suggestion}")
            
            review_section = "\n".join(review_lines)
    
    # 处理 layout（可能是字符串或 dict）
    if isinstance(layout, str):
        layout_direction = layout
    else:
        layout_direction = layout.get('direction', 'left to right') if isinstance(layout, dict) else 'left to right'
    
    # 构建提示词
    prompt = _build_prompt_base(overview, diagram_type, width, elements_desc, connections_desc, color_scheme, layout_direction, favicon_section, review_section)
    
    return prompt


def _build_prompt_base(overview: str, diagram_type: str, width: int, elements_desc: list, connections_desc: list, 
                       color_scheme: dict, layout_direction: str, favicon_section: str, review_section: str) -> str:
    """构建 SVG 生成 Prompt 的基础部分"""
    prompt = f"""## Task
Generate an SVG vector graphic based on the following precise description.

## Precise Description

- Overview: {overview}{favicon_section}
- Diagram Type: {diagram_type}
- Canvas Width: {width}px
- Layout Direction: {layout_direction}

{review_section}

## Elements ({len(elements_desc)})
"""

    for i, elem in enumerate(elements_desc):
        prompt += f"""
{i+1}. {elem['name']}
   - ID: {elem['id']}
   - Shape: {elem['shape']}
   - Color: {elem['color']}
   - Position: {elem['position']}
   - Size: {elem['size']}
   - Content Type: {elem['content_type']}
"""

    prompt += f"""
## Connections ({len(connections_desc)})
"""
    for i, conn in enumerate(connections_desc):
        prompt += f"""
{i+1}. {conn['from']} → {conn['to']}
   - Label: {conn['label']}
   - Style: {conn['style']}
   - Arrow: {conn['arrow']}
   - Color: {conn['color']}
"""

    prompt += f"""
## Color Scheme
- Background: {color_scheme.get('background', '#FFFFFF')}
- Primary: {color_scheme.get('primary', '#4A90D9')}
- Secondary: {color_scheme.get('secondary', '#7CB342')}
- Accent: {color_scheme.get('accent', '#F5A623')}
- Neutral: {color_scheme.get('neutral', '#9E9E9E')}
- Text: {color_scheme.get('text', '#333333')}

## Requirements

1. Generate complete SVG code with XML declaration and svg tag
2. Use standard SVG elements:
   - Rectangle: <rect>
   - Ellipse: <ellipse>
   - Diamond: <polygon>
   - Circle: <circle>
   - Connectors: <line> or <path>
   - Arrowheads: Use <marker> definition
   - Text: <text>
3. Layout rules:
   - Canvas width: {width}px, height auto-adaptive (recommended 400-800px)
   - Elements arranged {layout_direction}
   - Maintain proper spacing between elements (recommended 50-80px)
4. Style requirements:
   - Border: solid, 2px
   - Corner radius: 8px (use rx, ry attributes)
   - Text: clear font (Arial/Helvetica), 12-14px, dark color
   - Arrowheads: use marker-end to reference arrow markers
5. Keep academic and simple style: no complex gradients or shadows

## Output Format

Output ONLY the SVG code, no explanatory text or markdown code blocks!

Generate the SVG code now:"""

    return prompt

    return prompt


def call_multimodal_llm(prompt: str, config: dict, model_preference: str = None) -> str:
    """调用多模态大模型 API"""
    import urllib.request

    # 模型优先级: 用户指定 > MiniMax-M2.7-BF16 > Qwen3.5-397B-A17B > qwen25-vl
    available_models = ['MiniMax-M2.7-BF16', 'Qwen3.5-397B-A17B', 'qwen25-vl']
    if model_preference and model_preference in available_models:
        model = model_preference
    else:
        model = 'MiniMax-M2.7-BF16'
    
    api_url = f"http://llm.bnuzh.edu.cn:9180/v1/chat/completions"
    api_key = 'sk-AeGYLnhYWUEifWq7fedjCioDZssxEVraGzEcyhej9gQ1um6s'

    print(f"[调用多模态大模型] model: {model}", flush=True)

    headers = {'Content-Type': 'application/json', 'Authorization': f'Bearer {api_key}'}
    messages = [{"role": "user", "content": prompt}]

    data = {
        'model': model,
        'messages': messages,
        'temperature': 0.2,
        'max_tokens': 8000
    }

    req = urllib.request.Request(
        api_url,
        data=json.dumps(data).encode('utf-8'),
        headers=headers,
        method='POST'
    )

    try:
        with urllib.request.urlopen(req, timeout=300) as response:
            result = json.loads(response.read().decode('utf-8'))
            msg = result['choices'][0]['message']
            content = msg.get('content')
            if not content and msg.get('reasoning_content'):
                reasoning = msg['reasoning_content']
                json_match = re.search(r'<svg[\s\S]*?</svg>', reasoning, re.IGNORECASE)
                if json_match:
                    content = json_match.group()
                else:
                    # 尝试找代码块中的内容
                    code_match = re.search(r'```(?:svg)?\s*([\s\S]*?)```', reasoning, re.IGNORECASE)
                    if code_match:
                        content = code_match.group(1)
            return content
    except Exception as e:
        print(f"API调用失败: {e}", file=sys.stderr)
        return None


def extract_svg(response: str) -> str:
    """从响应中提取 SVG 代码"""
    if not response:
        return None

    # 移除 markdown 代码块
    clean_response = response.strip()
    
    # 先移除思考内容标签 (<think>,</think>)
    clean_response = re.sub(r'<think>[\s\S]*?</think>', '', clean_response)
    clean_response = re.sub(r'</?thinking>', '', clean_response)
    
    # 移除 ```svg 或 ``` 等代码块标记
    if '```' in clean_response:
        # 提取代码块内容
        code_match = re.search(r'```(?:svg)?\s*([\s\S]*?)\s*```', clean_response, re.IGNORECASE)
        if code_match:
            clean_response = code_match.group(1).strip()
        else:
            # 移除第一行的 ``` 和最后一行的 ```
            lines = clean_response.split('\n')
            if lines[0].strip().startswith('```'):
                lines = lines[1:]
            if lines and lines[-1].strip() == '```':
                lines = lines[:-1]
            clean_response = '\n'.join(lines)

    # 尝试提取 svg 标签
    svg_match = re.search(r'<svg[\s\S]*?</svg>', clean_response, re.IGNORECASE)
    if svg_match:
        return svg_match.group()

    # 如果没有找到，尝试在整个响应中搜索（包括 reasoning 内容）
    # 先移除思考内容
    response_no_think = re.sub(r'<think>[\s\S]*?</think>', '', response)
    full_match = re.search(r'<svg[\s\S]*?</svg>', response_no_think, re.IGNORECASE)
    if full_match:
        return full_match.group()
    
    # 如果还是没有，检查是否有 <svg 开头
    if '<svg' in clean_response:
        # 返回从 <svg 开始的所有内容
        start = clean_response.find('<svg')
        return clean_response[start:]

    return None


def validate_svg(svg_code: str) -> bool:
    """验证 SVG 代码基本有效性"""
    if not svg_code:
        return False

    # 检查基本标签
    has_svg_open = '<svg' in svg_code
    has_svg_close = '</svg>' in svg_code or '/svg>' in svg_code.lower()
    has_xml_decl = '<?xml' in svg_code or svg_code.strip().startswith('<svg')

    return has_svg_open and (has_svg_close or '/svg>' in svg_code.lower())


def generate_icon_image(icon_description: str, element_name: str, output_dir: str, config: dict) -> str:
    """调用图像生成模型生成图标，返回 Base64 编码的数据 URI"""
    import urllib.request
    import hashlib
    import base64
    
    # 使用元素名称和描述生成唯一标识
    element_hash = hashlib.md5(f"{element_name}_{icon_description}".encode()).hexdigest()[:8]
    icon_filename = f"icon_{element_hash}.png"
    icon_path = Path(output_dir) / icon_filename
    
    # 如果已存在则直接读取并返回 Base64
    if icon_path.exists():
        with open(icon_path, 'rb') as f:
            b64_data = base64.b64encode(f.read()).decode('utf-8')
        return f"data:image/png;base64,{b64_data}"
    
    # 构建图像生成 prompt - 要求彩色图标，透明背景
    prompt = f"Colorful flat icon for {element_name}. {icon_description}. Colorful design, flat style with multiple vibrant colors, TRANSPARENT background only (no white or colored background), icon format. Must use multiple colors."
    
    api_url = "http://llm.bnuzh.edu.cn:9180/v1/images/generations"
    api_key = 'sk-AeGYLnhYWUEifWq7fedjCioDZssxEVraGzEcyhej9gQ1um6s'
    
    print(f"[生成图标] {element_name}: {icon_description}", flush=True)
    
    headers = {'Content-Type': 'application/json', 'Authorization': f'Bearer {api_key}'}
    data = {
        'model': 'qwen-image',
        'prompt': prompt,
        'size': '512x512',
        'quality': 'standard',
        'n': 1
    }
    
    try:
        req = urllib.request.Request(
            api_url,
            data=json.dumps(data).encode('utf-8'),
            headers=headers,
            method='POST'
        )
        with urllib.request.urlopen(req, timeout=120) as response:
            result = json.loads(response.read().decode('utf-8'))
            # 支持 url 或 base64 格式
            image_data = result['data'][0]
            b64_data = None
            
            if 'url' in image_data and image_data['url']:
                image_url = image_data['url']
                # 下载图片
                img_req = urllib.request.Request(image_url)
                with urllib.request.urlopen(img_req) as img_resp:
                    img_bytes = img_resp.read()
                    icon_path.write_bytes(img_bytes)
                    b64_data = base64.b64encode(img_bytes).decode('utf-8')
            elif 'b64_json' in image_data and image_data['b64_json']:
                # 直接使用 base64 数据
                img_data = image_data['b64_json']
                # 移除 data:image 前缀（如果有）
                if ',' in img_data:
                    img_data = img_data.split(',')[1]
                b64_data = img_data
                icon_path.write_bytes(base64.b64decode(b64_data))
            else:
                print(f"[图标生成失败] 未找到 url 或 base64", flush=True)
                return None
            
            print(f"[保存图标] {icon_path}", flush=True)
            # 返回 Base64 数据 URI
            return f"data:image/png;base64,{b64_data}"
    except Exception as e:
        print(f"[图标生成失败] {e}", flush=True)
        return None


def embed_icons_in_svg(svg_code: str, icon_map: dict) -> str:
    """
    将 SVG 中的外部图标引用替换为 Base64 内嵌数据
    
    Args:
        svg_code: LLM 生成的 SVG 代码
        icon_map: 字典，key 为元素 ID，value 为 Base64 数据 URI
    
    Returns:
        替换后的 SVG 代码
    """
    if not icon_map:
        return svg_code
    
    import re
    
    # 获取所有 icon 值的列表（按顺序）
    icon_values = list(icon_map.values())
    if not icon_values:
        return svg_code
    
    # 找到所有 <image> 标签
    # 匹配模式：<image ... href="..." ... /> 或 <image ... href="..." ...></image>
    image_pattern = r'(<image[^>]*href=")[^"]+("[^>]*>)'
    
    def replace_image(match):
        # 使用一个计数器来依次替换每个图像
        if not hasattr(replace_image, 'counter'):
            replace_image.counter = 0
        
        idx = replace_image.counter
        replace_image.counter += 1
        
        if idx < len(icon_values):
            return match.group(1) + icon_values[idx] + match.group(2)
        return match.group(0)  # 如果没有更多图标，保持原样
    
    # 替换所有图像标签
    svg_code = re.sub(image_pattern, replace_image, svg_code)
    
    # 重置计数器（为了可能的多次调用）
    replace_image.counter = 0
    
    return svg_code


def save_svg(svg_code: str, output_path: str) -> bool:
    """保存 SVG 文件"""
    try:
        # 确保目录存在
        Path(output_path).parent.mkdir(parents=True, exist_ok=True)

        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(svg_code)

        print(f"[保存] SVG 已保存到: {output_path}", flush=True)
        return True
    except Exception as e:
        print(f"[错误] 保存 SVG 失败: {e}", file=sys.stderr)
        return False


def main():
    parser = argparse.ArgumentParser(
        description='使用多模态大模型生成 SVG 矢量图'
    )
    parser.add_argument(
        '-d', '--description',
        required=True,
        help='插图描述文件路径 (JSON)'
    )
    parser.add_argument(
        '-o', '--output',
        default='output/diagram.svg',
        help='输出 SVG 文件路径 (默认: output/diagram.svg)'
    )
    parser.add_argument(
        '-m', '--model',
        default='qwen3.5-397b-a17b',
        help='多模态模型名称 (默认: qwen3.5-397b-a17b)'
    )
    parser.add_argument(
        '-w', '--width',
        type=int,
        default=DEFAULT_WIDTH,
        help=f'SVG 画布宽度 (默认: {DEFAULT_WIDTH})'
    )
    parser.add_argument(
        '-c', '--config',
        default=DEFAULT_CONFIG_PATH,
        help=f'配置文件路径 (默认: {DEFAULT_CONFIG_PATH})'
    )
    parser.add_argument(
        '-r', '--review',
        action='store_true',
        help='生成SVG后调用多模态模型进行评价'
    )
    parser.add_argument(
        '--review-input',
        help='输入的review JSON文件路径，用于在生成时参考修改意见'
    )

    args = parser.parse_args()

    # 加载配置
    try:
        config = load_config(args.config)
    except FileNotFoundError:
        print(f"[错误] 配置文件不存在: {args.config}", file=sys.stderr)
        sys.exit(1)

    # 检查模型配置
    if args.model not in config.get('vision_models', {}):
        print(f"[错误] 未配置的模型: {args.model}", file=sys.stderr)
        print(f"可用模型: {list(config.get('vision_models', {}).keys())}", file=sys.stderr)
        sys.exit(1)

    # 加载插图描述
    try:
        description = load_description(args.description)
    except FileNotFoundError:
        print(f"[错误] 描述文件不存在: {args.description}", file=sys.stderr)
        sys.exit(1)
    except json.JSONDecodeError as e:
        print(f"[错误] 描述文件 JSON 解析失败: {e}", file=sys.stderr)
        sys.exit(1)

    print(f"[信息] 加载描述文件: {args.description}", flush=True)
    diagram_type = description.get('diagram_type', 'Unknown')
    elements = description.get('elements', [])
    connections = description.get('connections', [])
    
    # 兼容简略格式：只有 name 没有完整字段
    if elements and isinstance(elements[0], dict) and 'name' in elements[0] and 'id' not in elements[0]:
        # 转换简略格式
        elements = [{"id": f"elem_{i+1}", "name": e.get('name', ''), **e} for i, e in enumerate(elements)]
    if connections and isinstance(connections[0], dict) and 'from' not in connections[0]:
        # 转换简略格式
        connections = []
    
    # [图标功能已注释] 预先处理 icon 类型的元素
    # icon_map = {}
    # output_dir = str(Path(args.output).parent)
    # for elem in elements:
    #     # 支持 icon 和 mixed 类型
    #     content_type = elem.get('content_type', '')
    #     if (content_type == 'icon' or content_type == 'mixed') and elem.get('icon_description'):
    #         icon_path = generate_icon_image(
    #             elem.get('icon_description', ''),
    #             elem.get('name', ''),
    #             output_dir,
    #             config
    #         )
    #         if icon_path:
    #             icon_map[elem.get('id')] = icon_path
    
    # # 如果有图标，在 overview 中添加说明
    # if icon_map:
    #     print(f"[信息] 预生成图标数量: {len(icon_map)}", flush=True)
    
    # # 替换 icon_map 中的文件路径为 Base64 数据（generate_icon_image 已返回 Base64）
    # # icon_map 现在是 {elem_id: base64_data_uri}
    # for elem_id, icon_data in list(icon_map.items()):
    #     # 如果是文件路径而非 base64，读取并转换
    #     if not icon_data.startswith('data:'):
    #         import base64
    #         with open(icon_data, 'rb') as f:
    #             b64_data = base64.b64encode(f.read()).decode('utf-8')
    #         icon_map[elem_id] = f"data:image/png;base64,{b64_data}"
    
    # 图标功能已注释，设为空字典
    icon_map = {}
    
    # 构建 prompt
    # 如果指定了 review-input，加载 review 数据
    review_data = None
    if args.review_input:
        try:
            with open(args.review_input, 'r', encoding='utf-8') as f:
                review_data = json.load(f)
            print(f"[信息] 已加载 review: {args.review_input}", flush=True)
        except Exception as e:
            print(f"[警告] 加载 review 失败: {e}", flush=True)
    
    # 根据是否有 review 数据选择不同的 prompt 构建方式
    if review_data:
        # 有 review: 使用带 review 的 prompt（会读取原 SVG 内容）
        prompt = build_svg_prompt_with_review(description, args.width, icon_map, review_data)
    else:
        # 无 review: 使用基础 prompt
        prompt = build_svg_prompt(description, args.width, icon_map, None)
    
    print(f"[信息] 图表类型: {diagram_type}", flush=True)
    print(f"[信息] 元素数量: {len(elements)}", flush=True)
    print(f"[信息] 连接数量: {len(connections)}", flush=True)
    print(f"[信息] 构建 SVG 生成 Prompt 完成", flush=True)

    # 调用大模型
    response = call_multimodal_llm(prompt, config)
    if not response:
        print("[错误] 大模型调用失败", file=sys.stderr)
        sys.exit(1)

    print(f"[信息] 大模型响应长度: {len(response)} 字符", flush=True)

    # 提取 SVG
    svg_code = extract_svg(response)
    if not svg_code:
        print("[错误] 无法从响应中提取 SVG 代码", file=sys.stderr)
        print(f"[调试] 响应内容前500字符: {response[:500]}", file=sys.stderr)
        sys.exit(1)

    # [图标功能已注释] 将图标内嵌到 SVG 中
    # if icon_map:
    #     svg_code = embed_icons_in_svg(svg_code, icon_map)
    #     print(f"[信息] 图标已内嵌到 SVG", flush=True)
    
    # 验证 SVG
    if not validate_svg(svg_code):
        print("[警告] SVG 代码验证未通过，尝试保存...", file=sys.stderr)

    # 保存 SVG
    if save_svg(svg_code, args.output):
        print(f"[完成] SVG 生成成功: {args.output}", flush=True)
    else:
        sys.exit(1)
    
    # 调用 review 脚本进行图片评价
    if args.review:
        import subprocess
        review_output = Path(args.output).with_suffix('.review.json')
        try:
            cmd = [
                'python3',
                str(Path(__file__).parent / 'review_svg.py'),
                '-s', args.output,
                '-d', args.description,
                '-o', str(review_output)
            ]
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=180)
            if result.returncode == 0:
                print(f"[完成] SVG 评价完成: {review_output}", flush=True)
            else:
                print(f"[警告] SVG 评价失败: {result.stderr}", flush=True)
        except Exception as e:
            print(f"[警告] SVG 评价异常: {e}", flush=True)


if __name__ == '__main__':
    main()
