"""即梦(Jimeng) video adapter — Volcengine SDK Implementation.
Supports text-to-video via CVSync2AsyncSubmitTask."""
import json
import os
import sys
import time

import requests
from volcengine.visual.VisualService import VisualService


class JimengVideoAdapter:
    POLL_INTERVAL = 10
    MAX_WAIT = 600

    def generate(self, prompt, config, **kwargs):
        access_key = config["access_key"]
        secret_key = config["secret_key"]
        req_key = config.get("model", "jimeng_t2v_v30")
        out_dir = kwargs["out_dir"]

        # duration → frames: 5s=121, 10s=241 (assuming default 5s max logic for now, standard expects 121 for 5s)
        duration = int(kwargs.get("duration", 5))
        frames = 24 * duration + 1

        aspect_ratio = kwargs.get("aspect_ratio", "16:9")

        # ═══ Step 1: 提交任务 ═══
        vs = VisualService()
        vs.set_ak(access_key)
        vs.set_sk(secret_key)

        body = {
            "req_key": req_key,
            "prompt": prompt,
            "seed": -1,
            "frames": frames,
            "aspect_ratio": aspect_ratio,
        }

        print(f"[jimeng_video] 提交文生视频任务 req_key={req_key}...", file=sys.stderr)
        try:
            data = vs.cv_sync2async_submit_task(body)
        except Exception as e:
            # Handle SDK exceptions which wrap the raw response
            if hasattr(e, 'args') and len(e.args) > 0 and isinstance(e.args[0], bytes):
                try:
                    err_json = json.loads(e.args[0].decode('utf-8'))
                    raise RuntimeError(f"即梦 API 错误: {err_json}")
                except RuntimeError:
                    raise
                except Exception:
                    pass
            raise RuntimeError(f"即梦提交失败: {str(e)}")

        if data.get("code") != 10000:
            raise RuntimeError(f"即梦 API 错误: {data.get('message')} (code={data.get('code')})")

        task_id = data["data"]["task_id"]
        print(f"[jimeng_video] task_id={task_id}, 开始轮询...", file=sys.stderr)

        # ═══ Step 2: 轮询状态 ═══
        video_url = None
        elapsed = 0
        while elapsed < self.MAX_WAIT:
            time.sleep(self.POLL_INTERVAL)
            elapsed += self.POLL_INTERVAL

            query_body = {
                "req_key": req_key,
                "task_id": task_id,
            }
            try:
                qdata = vs.cv_sync2async_get_result(query_body)
            except Exception as e:
                # Same exception handling for polling
                if hasattr(e, 'args') and len(e.args) > 0 and isinstance(e.args[0], bytes):
                    try:
                        err_json = json.loads(e.args[0].decode('utf-8'))
                        if err_json.get("code") in (50500, 50501):
                            continue # Server error, can retry
                        raise RuntimeError(f"即梦查询失败: {err_json}")
                    except RuntimeError:
                        raise
                    except Exception:
                        pass
                raise RuntimeError(f"即梦查询异常: {str(e)}")

            if qdata.get("code") != 10000:
                print(f"[jimeng_video] 轮询 {elapsed}s: code={qdata.get('code')} msg={qdata.get('message')}", file=sys.stderr)
                if qdata.get("code") in (50500, 50501):
                    continue  # 可重试的内部错误
                raise RuntimeError(f"即梦状态获取失败: {qdata.get('message')} (code={qdata.get('code')})")

            status = qdata.get("data", {}).get("status", "")
            print(f"[jimeng_video] 轮询 {elapsed}s: status={status}", file=sys.stderr)

            if status == "done":
                video_url = qdata["data"].get("video_url")
                break
            elif status in ("in_queue", "generating"):
                continue
            elif status in ("not_found", "expired"):
                raise RuntimeError(f"即梦任务异常停机: status={status}")

        if not video_url:
            raise RuntimeError(f"即梦视频生成超时 ({self.MAX_WAIT}s), task_id={task_id}")

        print(f"[jimeng_video] 生成完成, 下载中...", file=sys.stderr)

        # ═══ Step 3: 下载视频 ═══
        fname = kwargs.get("output_path") or os.path.join(out_dir, "video.mp4")
        r = requests.get(video_url, timeout=300)
        r.raise_for_status()
        with open(fname, "wb") as f:
            f.write(r.content)

        print(f"[jimeng_video] 已保存: {fname}", file=sys.stderr)
        return [fname]
