"use strict";

/**
 * 口播视频生成：调用 Gradio 数字人 API（对齐 Electron compshare:digitalHumanProcess）
 */

const fs = require("fs");
const path = require("path");
const os = require("os");
const { spawn } = require("child_process");
const desktopConfig = require("./desktop_config.js");

const TEMP_DIR = path.join(os.tmpdir(), "aiclient-digital-human");

function downloadFile(url, destPath) {
  return new Promise((resolve, reject) => {
    const client = url.startsWith("https") ? require("https") : require("http");
    const file = fs.createWriteStream(destPath);
    client
      .get(url, (res) => {
        if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
          file.close();
          return downloadFile(res.headers.location, destPath).then(resolve).catch(reject);
        }
        if (res.statusCode !== 200) {
          reject(new Error(`下载失败 HTTP ${res.statusCode}`));
          return;
        }
        res.pipe(file);
        file.on("finish", () => file.close(() => resolve(destPath)));
      })
      .on("error", reject);
  });
}

async function ensureLocalVideo(videoPath) {
  const raw = String(videoPath || "").trim();
  if (!raw) throw new Error("视频路径为空");
  if (/^https?:\/\//i.test(raw)) {
    fs.mkdirSync(TEMP_DIR, { recursive: true });
    const ext = raw.includes(".mp4") ? ".mp4" : ".mp4";
    const dest = path.join(TEMP_DIR, `remote_${Date.now()}${ext}`);
    await downloadFile(raw, dest);
    return dest;
  }
  if (raw.startsWith("file://")) {
    return raw.replace(/^file:\/\//, "");
  }
  return raw;
}

function runPythonDigitalHuman(apiUrl, audioFile, videoFile) {
  const scriptPath = path.join(__dirname, "digital_human_process.py");
  const py = process.env.AICLIENT_PYTHON || (process.platform === "win32" ? "python" : "python3");

  return new Promise((resolve) => {
    const child = spawn(py, [scriptPath, apiUrl, audioFile, videoFile], {
      cwd: __dirname,
      env: process.env,
      windowsHide: true,
    });
    let stdout = "";
    let stderr = "";
    child.stdout.on("data", (d) => {
      stdout += d.toString();
    });
    child.stderr.on("data", (d) => {
      stderr += d.toString();
    });
    child.on("error", (err) => {
      resolve({ success: false, error: err.message });
    });
    const timer = setTimeout(() => {
      child.kill();
      resolve({ success: false, error: "数字人处理超时（10 分钟）" });
    }, 600000);
    child.on("close", (code) => {
      clearTimeout(timer);
      if (code !== 0 || !stdout.trim()) {
        resolve({
          success: false,
          error: stderr.trim() || `数字人脚本退出码 ${code}`,
        });
        return;
      }
      try {
        const lines = stdout
          .split(/\r?\n/)
          .map((l) => l.trim())
          .filter(Boolean);
        const jsonLine = [...lines]
          .reverse()
          .find((l) => l.startsWith("{") && l.endsWith("}"));
        if (!jsonLine) {
          resolve({
            success: false,
            error: `解析结果失败: ${stdout.slice(0, 200)}`,
          });
          return;
        }
        resolve(JSON.parse(jsonLine));
      } catch (e) {
        resolve({
          success: false,
          error: `解析 JSON 失败: ${e.message}`,
        });
      }
    });
  });
}

globalThis.__nodejsMain = async function (params) {
  const p = params || {};
  const apiUrl =
    desktopConfig.get("DIGITAL_HUMAN_API_URL") ||
    desktopConfig.get("VIDEO_GEN_API_URL") ||
    desktopConfig.get("DIGITAL_HUMAN_GRADIO_URL");
  if (!apiUrl) {
    return {
      success: false,
      error:
        "缺少 DIGITAL_HUMAN_API_URL（或 VIDEO_GEN_API_URL），请在配置管理中设置数字人 Gradio 服务地址",
    };
  }

  const audioFile = String(p.audioPath || "").trim();
  const videoFile = String(p.avatarVideoPath || "").trim();
  if (!audioFile) {
    return { success: false, error: "缺少音频文件，请先生成语音" };
  }
  if (!videoFile) {
    return { success: false, error: "缺少形象视频，请先选择形象" };
  }
  if (!fs.existsSync(audioFile)) {
    return { success: false, error: `音频文件不存在: ${audioFile}` };
  }
  if (!fs.existsSync(videoFile)) {
    return { success: false, error: `形象视频不存在: ${videoFile}` };
  }

  const result = await runPythonDigitalHuman(apiUrl, audioFile, videoFile);
  if (!result?.success || !result?.videoPath) {
    return {
      success: false,
      error: String(result?.error || "口播视频生成失败"),
    };
  }

  try {
    const localPath = await ensureLocalVideo(result.videoPath);
    return { success: true, videoPath: localPath };
  } catch (e) {
    return { success: false, error: e.message || String(e) };
  }
};
