#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
MULTI-REFERENCE-VIDEO-ADAPTER
多参考图视频适配器 — 支持苏白+牌匾+场景多参考输入。

功能:
1. 检查视频API是否支持多参考图输入
2. 如果支持: 封装多参考图接口，统一调用
3. 如果不支持: 明确报错，回退到"单参考图+后期合成"路线
4. 提供统一的调用接口给上游 Agent

用法:
  python multi-reference-video-adapter.py --prompt "苏白站在天道宗牌匾下" \\
    --references char-003-subai.png tdz-plaque.png env-baizonghui.png \\
    --output output.mp4

检查API能力:
  python multi-reference-video-adapter.py --check-api
"""

import os
import sys
import json
import argparse
import requests
from pathlib import Path
from datetime import datetime

PROJECT_ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(PROJECT_ROOT / "engines"))

def load_api_config():
    """从仓库 .env、本机密钥文件和环境变量加载配置"""
    config = {}
    env_files = [
        Path(os.environ["VIDEO_AI_SECRETS_FILE"]) if os.environ.get("VIDEO_AI_SECRETS_FILE") else None,
        Path("/Users/bingshuolingdianyuanhe/Documents/guanghulab-local-secrets/video-ai-system.env"),
        PROJECT_ROOT / ".env",
    ]
    for env_file in env_files:
        if env_file is None:
            continue
        if not env_file.exists():
            continue
        with open(env_file, "r", encoding="utf-8") as f:
            for line in f:
                line = line.strip()
                if line and not line.startswith("#"):
                    key, _, val = line.partition("=")
                    config[key.strip()] = val.strip().strip('"').strip("'")
    for key in ["JIMENG_API_KEY", "JIMENG_BASE_URL", "JIMENG_MODEL"]:
        if os.environ.get(key):
            config[key] = os.environ[key]
    return config


class MultiReferenceVideoAdapter:
    """多参考图视频适配器"""

    def __init__(self, live_capability_check=False, allow_single_reference_fallback=False):
        self.config = load_api_config()
        self.api_key = self.config.get("JIMENG_API_KEY", "")
        self.base_url = self.config.get("JIMENG_BASE_URL", "https://ark.cn-beijing.volces.com/api/v3")
        self.model = self.config.get("JIMENG_MODEL", "doubao-seedance-2-0-260128")
        self.live_capability_check = live_capability_check
        self.allow_single_reference_fallback = allow_single_reference_fallback

        # API 能力探测结果缓存
        self._api_capabilities = None

    def check_api_capabilities(self, live=None):
        """
        检查 API 是否支持多参考图
        返回: {
            "multi_reference_supported": bool,
            "max_references": int,
            "supported_types": list,  # ["image_url", "image_url_2", ...]
            "details": str
        }
        """
        if self._api_capabilities:
            return self._api_capabilities

        live = self.live_capability_check if live is None else live
        print("🔍 检查 Seedance API 多参考图支持...")

        # 根据 Volcengine 官方文档 (https://www.volcengine.com/docs/82379/1520757)
        # Seedance 2.0 API 的 content 数组支持多个 image_url 对象
        # 但需要实际测试确认

        # 理论上的 API 结构:
        # content: [
        #   { type: "text", text: "..." },
        #   { type: "image_url", image_url: { url: "data:image/png;base64,..." } },
        #   { type: "image_url", image_url: { url: "data:image/png;base64,..." } },  # 第二张参考图
        # ]

        if not live:
            test_result = {
                "multi_reference_supported": False,
                "max_references": 1,
                "supported_types": ["image_url"],
                "status": "unverified",
                "details": "未执行付费/联网实测；需要 --live-check 才会提交真实 API 探测任务",
                "requires_live_check": True
            }
        else:
            test_result = self._test_multi_reference()

        self._api_capabilities = test_result
        return test_result

    def _test_multi_reference(self):
        """
        实际测试 API 是否支持多参考图
        方法: 提交一个测试请求，包含2张参考图，观察响应
        """
        if not self.api_key:
            return {
                "multi_reference_supported": False,
                "max_references": 1,
                "supported_types": ["image_url"],
                "details": "未找到 JIMENG_API_KEY，无法执行 live check",
                "status": "missing_api_key"
            }

        # 构造一个最小测试请求
        test_prompt = "test multi-reference support"

        # 创建1x1像素的测试图片 (PNG)
        import base64
        from io import BytesIO
        try:
            from PIL import Image
            img = Image.new("RGB", (32, 32), color=(255, 0, 0))
            buf = BytesIO()
            img.save(buf, format="PNG")
            test_img_b64 = base64.b64encode(buf.getvalue()).decode()
        except ImportError:
            # 如果没有 PIL，用空base64
            test_img_b64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWg"

        # 构造 content 数组 (2张参考图)
        content = [
            {"type": "text", "text": test_prompt},
            {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{test_img_b64}"}},
            {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{test_img_b64}"}},
        ]

        payload = {
            "model": self.model,
            "content": content,
            "duration": 4,  # 最短时长，省钱
            "resolution": "480p"
        }

        # 发送请求
        try:
            print("  📤 发送测试请求 (2张参考图)...")
            url = f"{self.base_url}/contents/generations/tasks"
            headers = {
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            }

            response = requests.post(url, json=payload, headers=headers, timeout=30)

            if response.status_code == 200:
                # 成功！API 支持多参考图
                print("  ✅ API 支持多参考图！")
                return {
                    "multi_reference_supported": True,
                    "max_references": 2,  # 需要逐步测试确定上限
                    "supported_types": ["image_url"],
                    "details": "API 成功接受2张参考图"
                }
            elif response.status_code == 400:
                # 看错误信息
                error_data = response.json()
                error_msg = error_data.get("error", {}).get("message", "")
                print(f"  ❌ API 不支持多参考图: {error_msg}")
                return {
                    "multi_reference_supported": False,
                    "max_references": 1,
                    "supported_types": ["image_url"],  # 只支持单张
                    "details": error_msg,
                    "error_response": error_data
                }
            else:
                print(f"  ⚠️  未知响应: {response.status_code}")
                return {
                    "multi_reference_supported": False,
                    "max_references": 1,
                    "details": f"Unknown response: {response.status_code}"
                }

        except Exception as e:
            print(f"  ❌ 测试失败: {e}")
            return {
                "multi_reference_supported": False,
                "max_references": 1,
                "details": f"Test failed: {e}"
            }

    def generate_video(self, prompt, reference_images, output_path=None, duration=5, resolution="720p"):
        """
        生成视频 (多参考图)

        参数:
          prompt: str - 提示词
          reference_images: list[str] - 参考图路径列表
          output_path: str - 输出路径
          duration: int - 时长 (4-15)
          resolution: str - 分辨率 ("480p" | "720p")

        返回:
          {
            "success": bool,
            "task_id": str,
            "output_path": str,
            "method": str,  # "multi-reference" | "single-reference+composite"
            "warning": str
          }
        """
        print(f"\n🎬 生成视频 (多参考图)")
        print(f"   提示词: {prompt[:60]}...")
        print(f"   参考图数量: {len(reference_images)}")
        for i, img in enumerate(reference_images):
            print(f"      [{i+1}] {Path(img).name}")

        # 检查 API 能力
        capabilities = self.check_api_capabilities()

        if capabilities["multi_reference_supported"]:
            # API 支持多参考图 → 直接调用
            print(f"\n  ✅ API 支持多参考图，直接调用...")
            result = self._generate_multi_reference(prompt, reference_images, output_path, duration, resolution)
            result["method"] = "multi-reference"
            return result
        else:
            # API 不支持多参考图 → 明确报错 + 建议回退方案
            print(f"\n  ❌ API 不支持多参考图")
            print(f"  📋 错误详情: {capabilities['details']}")
            print(f"\n  💡 回退方案:")
            print(f"     1. 使用第一张参考图 (苏白) 生成视频")
            print(f"     2. 后期合成牌匾/场景 (平面追踪 + 贴图)")
            print(f"     3. 或使用可灵生成角色，Seedance 生成场景，后期合成")

            if not self.allow_single_reference_fallback:
                return {
                    "success": False,
                    "method": "not-run",
                    "error": "多参考图能力未确认或不支持，未自动回退单参考图以避免误导一致性测试",
                    "capabilities": capabilities,
                    "next_step": "使用 --live-check 验证多参考图，或显式传入 --allow-single-reference-fallback 做调试占位"
                }

            # 回退: 只用第一张参考图。必须显式开启，避免误导牌匾/场景一致性判断。
            warning = "API不支持多参考图，已回退到单参考图模式。牌匾/场景一致性需要后期合成。"
            print(f"\n  🔄 回退: 使用第一张参考图生成...")

            result = self._generate_single_reference(prompt, reference_images[0], output_path, duration, resolution)
            result["method"] = "single-reference+composite"
            result["warning"] = warning
            result["fallback_reason"] = capabilities["details"]

            return result

    def _generate_multi_reference(self, prompt, reference_images, output_path, duration, resolution):
        """调用多参考图 API"""
        # 构造 content 数组
        content = [{"type": "text", "text": prompt}]

        for img_path in reference_images:
            img_path = Path(img_path)
            if not img_path.exists():
                print(f"  ⚠️  参考图不存在: {img_path}")
                continue

            # 读取图片并转 base64
            import base64
            with open(img_path, "rb") as f:
                img_data = f.read()
            b64 = base64.b64encode(img_data).decode()
            mime = "image/png" if img_path.suffix.lower() == ".png" else "image/jpeg"

            content.append({
                "type": "image_url",
                "image_url": {"url": f"data:{mime};base64,{b64}"}
            })

        # 调用 API
        payload = {
            "model": self.model,
            "content": content,
            "duration": duration,
            "resolution": resolution
        }

        print(f"  📤 提交任务...")
        url = f"{self.base_url}/contents/generations/tasks"
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }

        response = requests.post(url, json=payload, headers=headers, timeout=60)
        response.raise_for_status()
        data = response.json()

        task_id = data.get("id") or data.get("task_id")
        print(f"  ✅ 任务已提交: {task_id}")

        # 返回任务ID，等待轮询
        return {
            "success": True,
            "task_id": task_id,
            "output_path": output_path,
            "api_response": data
        }

    def _generate_single_reference(self, prompt, reference_image, output_path, duration, resolution):
        """回退: 单参考图生成"""
        # 调用现有的 video-api-adapter (Node.js)
        # 这里用 subprocess 调用
        import subprocess

        print(f"  📤 调用单参考图 API...")

        # 构造调用参数
        node_script = PROJECT_ROOT / "engines" / "video-api-adapter.js"
        cmd = [
            "node", str(node_script),
            "--prompt", prompt,
            "--reference-image", str(reference_image),
            "--duration", str(duration),
            "--resolution", resolution
        ]

        # 执行
        result = subprocess.run(cmd, capture_output=True, text=True)
        if result.returncode != 0:
            print(f"  ❌ 调用失败: {result.stderr}")
            return {"success": False, "error": result.stderr}

        print(f"  ✅ 任务已提交")
        return {"success": True, "method": "single-reference", "stdout": result.stdout}

    def batch_generate(self, shots_config):
        """
        批量生成 (从配置文件)

        shots_config 格式:
          [
            {
              "shot_id": "E1-SHOT01",
              "prompt": "...",
              "references": ["char.png", "prop.png", "env.png"],
              "output": "output/E1-SHOT01.mp4"
            },
            ...
          ]
        """
        results = []
        for shot in shots_config:
            result = self.generate_video(
                prompt=shot["prompt"],
                reference_images=shot["references"],
                output_path=shot["output"]
            )
            results.append(result)
        return results


def main():
    parser = argparse.ArgumentParser(description="MULTI-REFERENCE-VIDEO-ADAPTER")
    parser.add_argument("--check-api", action="store_true", help="检查API多参考图支持")
    parser.add_argument("--live-check", action="store_true",
                        help="执行真实 API 探测请求，可能产生费用")
    parser.add_argument("--allow-single-reference-fallback", action="store_true",
                        help="多参考图不可用时允许单参考图调试占位")
    parser.add_argument("--prompt", type=str, help="提示词")
    parser.add_argument("--references", type=str, nargs="+", help="参考图路径列表")
    parser.add_argument("--output", type=str, help="输出路径")
    parser.add_argument("--duration", type=int, default=5, help="时长 (4-15)")
    parser.add_argument("--resolution", type=str, default="720p", choices=["480p", "720p"], help="分辨率")

    args = parser.parse_args()

    adapter = MultiReferenceVideoAdapter(
        live_capability_check=args.live_check,
        allow_single_reference_fallback=args.allow_single_reference_fallback
    )

    if args.check_api:
        capabilities = adapter.check_api_capabilities(live=args.live_check)
        print(f"\n📊 API 能力报告:")
        print(f"   多参考图支持: {capabilities['multi_reference_supported']}")
        print(f"   最大参考图数: {capabilities['max_references']}")
        print(f"   详情: {capabilities['details']}")
        return

    if not args.prompt or not args.references:
        parser.print_help()
        return

    result = adapter.generate_video(
        prompt=args.prompt,
        reference_images=args.references,
        output_path=args.output,
        duration=args.duration,
        resolution=args.resolution
    )

    print(f"\n📋 生成结果:")
    print(json.dumps(result, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
