"use strict";

/**
 * douyin_pipeline.js — Node 完整仿写流水线
 * 对齐 quickjs/douyin_pipeline.js 与 Electron VideoRewriteIntegration.processDouyinShareComplete
 *
 * 由后端 `/api/v1/nodejs-scripts` 下发；Tauri 调用 run_nodejs_script → __nodejsMain(params)
 */

const { DouyinContentParser } = require("./douyin_content_parser.js");
const { DouyinVideoDownloader } = require("./douyin_video_downloader.js");
const { VideoRewriteOptimizer } = require("./video_rewrite_optimizer.js");
const pipelineNative = require("./pipeline_native.js");
const desktopConfig = require("./desktop_config.js");

/**
 * Tauri 子进程内请用 __native.log（stderr __EVT__ → Rust → nodejs:event）。
 * console.* 被管道接管，不会出现在 tauri dev 终端；仅在没有 __native 时回退到控制台。
 */
const log = (level, msg, fields) => {
  if (globalThis.__native?.log) {
    globalThis.__native.log(level, msg, fields == null ? null : fields);
    return;
  }
  const tag = `[pipeline.${level}] ${msg}`;
  if (fields != null) {
    if (level === "error") console.error(tag, fields);
    else if (level === "warn") console.warn(tag, fields);
    else console.log(tag, fields);
  } else if (level === "error") console.error(tag);
  else if (level === "warn") console.warn(tag);
  else console.log(tag);
};
const progress = (s) => {
  try {
    globalThis.__native.emitProgress(s);
  } catch (_) {
    /* ignore */
  }
};

async function rewriteWithAI(content, modelConfig, rewriteConfig, customPrompt) {
  if (!modelConfig?.apiUrl || !modelConfig?.apiKey) {
    log("error", "rewrite.missingConfig");
    return null;
  }
  const prompt = VideoRewriteOptimizer.buildRewritePrompt(
    content,
    rewriteConfig || {},
    customPrompt
  );
  log("info", "pipeline.rewritePrompt", { prompt: prompt });
  log("info", "pipeline.apiUrl", { apiUrl: modelConfig.apiUrl });
  log("info", "pipeline.apiKey", { apiKey: modelConfig.apiKey });
  log("info", "pipeline.apiModelId", { apiModelId: modelConfig.apiModelId });
  const result = await pipelineNative.openaiChat({
    apiUrl: modelConfig.apiUrl,
    apiKey: modelConfig.apiKey,
    model: modelConfig.apiModelId,
    messages: [
      { role: "system", content: "你是专业的短视频文案改写助手。请把用户提供的文案改写,要求保持原文的风格和主题，但使用不同的表达方式。" },
      { role: "user", content: prompt },
    ],
    temperature: 0.8,
    max_tokens: 2e3,
  });
  if (!result?.success) {
    log("error", "rewrite.failed", { error: result?.error });
    return null;
  }
  log("info", "pipeline.rewriteOk", { result: result.content });
  return result.content;
}

/**
 * 完整流程：解析 → Puppeteer/直链下载 → ffmpeg 提音频 → ASR → AI 仿写
 */
async function processDouyinShareComplete(
  shareText,
  modelConfig,
  rewriteConfig,
  customPrompt
) {
  let videoPath = null;
  let audioPath = null;
  try {
    log("info", "pipeline.start", {
      inputLength: shareText?.length,
      asrMode: modelConfig?.asrMode,
    });

    progress("正在解析视频URL...");
    const parseResult = DouyinContentParser.parseContent(shareText);
    if (!parseResult.success || !parseResult.content) {
      return { success: false, error: parseResult.error || "内容解析失败" };
    }

    const { videoUrl, hashtags } = parseResult.content;
    log("info", "pipeline.urlExtracted", { videoUrl });

    progress("正在下载视频...");
    const downloader = new DouyinVideoDownloader();
    const downloadResult = DouyinContentParser.isDirectVideoUrl(videoUrl)
      ? await downloader.downloadDirectVideo(videoUrl)
      : await downloader.downloadDouyinVideo(videoUrl);

    if (!downloadResult.success || !downloadResult.videoPath) {
      return {
        success: false,
        error: downloadResult.error || "视频下载失败",
      };
    }
    videoPath = downloadResult.videoPath;
    log("info", "pipeline.videoDownloaded", { videoPath });

    progress("视频下载完成，正在提取音频...");
    try {
      audioPath = await pipelineNative.ffmpegExtractAudio(videoPath);
    } catch (e) {
      return {
        success: false,
        error: `音频提取失败: ${e.message || e}`,
      };
    }
    log("info", "pipeline.audioExtracted", { audioPath });

    const asrMode = modelConfig?.asrMode || "online";
    let recognizedText = "";

    if (asrMode === "online") {
      progress("音频提取完成，正在上传到OSS...");
      const ossConfig = modelConfig.ossConfig;
      if (!ossConfig?.bucket) {
        return { success: false, error: "未配置阿里云 OSS（bucket / region / key）" };
      }
      const upload = await pipelineNative.aliyunOssUpload(audioPath, ossConfig);
      if (!upload?.success || !upload.url) {
        return {
          success: false,
          error: `音频上传失败: ${upload?.error || "unknown"}`,
        };
      }
      log("info", "pipeline.ossOk", { audioUrl: upload.url });

      progress("音频上传完成，正在识别文案（在线模式）...");
      const asr = await pipelineNative.aliyunAsrFiletrans(upload.url, {
        apiKey: modelConfig.aliyunApiKey,
        model: "qwen3-asr-flash-filetrans",
      });
      if (!asr?.success) {
        return {
          success: false,
          error: `语音识别失败（在线模式）: ${asr?.error || "unknown"}`,
        };
      }
      recognizedText = asr.text || "";
    } else {
      progress("音频提取完成，正在识别文案（本地模式）...");
      const info = modelConfig.asrServerInfo;
      if (!info) {
        return {
          success: false,
          error: "未配置本地语音识别服务器，请在 .env 中配置 VITE_ASR_SERVER_URL",
        };
      }
      const asr = await pipelineNative.localAsr(audioPath, info);
      if (!asr?.success) {
        return {
          success: false,
          error: `语音识别失败（本地模式）: ${asr?.error || "unknown"}`,
        };
      }
      recognizedText = asr.text || "";
    }

    if (!modelConfig?.apiUrl || !modelConfig?.apiKey) {
      return { success: false, error: "未配置AI模型，请先在 .env 中配置" };
    }

    progress("文案识别完成，正在改写...");
    const rewrittenDescription = await rewriteWithAI(
      recognizedText,
      modelConfig,
      rewriteConfig,
      customPrompt
    );
    if (!rewrittenDescription) {
      return {
        success: false,
        error: "AI仿写失败，请检查模型配置和网络连接",
      };
    }

    const rewrittenTitle =
      DouyinContentParser.generateTitleFromDescription(rewrittenDescription);
    const keepTags = rewriteConfig?.keepHashtags !== false;
    const fullContent =
      keepTags && hashtags?.length
        ? `${rewrittenDescription}\n\n${hashtags.join(" ")}`
        : rewrittenDescription;

    progress("完成！");
    log("info", "pipeline.success", {
      originalLength: recognizedText.length,
      rewrittenLength: rewrittenDescription.length,
    });

    return {
      success: true,
      original: {
        videoUrl,
        description: recognizedText,
        hashtags: hashtags || [],
        title: "视频音频识别结果",
      },
      rewritten: {
        description: rewrittenDescription,
        title: rewrittenTitle,
        fullContent,
      },
    };
  } catch (e) {
    const msg = (e && (e.stack || e.message)) || String(e);
    log("error", "pipeline.error", { message: msg });
    return { success: false, error: msg };
  } finally {
    if (videoPath) pipelineNative.deleteFile(videoPath);
    if (audioPath) pipelineNative.deleteFile(audioPath);
  }
}

globalThis.__nodejsMain = async function (params) {
  const p = params || {};
  const modelConfig = desktopConfig.buildModelConfig();
  const check = desktopConfig.validateModelConfig(modelConfig);
  if (!check.ok) {
    return { success: false, error: check.error };
  }
  return processDouyinShareComplete(
    p.shareText || p.share_text || "",
    modelConfig,
    p.rewriteConfig,
    p.customPrompt || null
  );
};
