import { spawn } from "child_process";
import { promises as fs } from "fs";
import { getVideoConfig } from "@/lib/generation/video-config";
import type { SocialImageContext } from "@/lib/generation/social-image";

/** Build a short VO script from brand + story slides (no invented facts). */
export function buildVideoNarrationScript(ctx: SocialImageContext, caption?: string): string {
  const company = ctx.companyName || "our team";
  const parts = [
    ctx.headline,
    ctx.problemTheme,
    ctx.subheadline || ctx.brandStyle.tagline,
    ctx.brandResponse || ctx.brandStyle.primaryService,
    ctx.brandStyle.ctaLine,
  ]
    .map((p) => (p || "").replace(/\s+/g, " ").trim())
    .filter(Boolean);

  const unique: string[] = [];
  for (const part of parts) {
    if (!unique.some((u) => u.toLowerCase() === part.toLowerCase())) unique.push(part);
  }

  const body = unique.slice(0, 5).join(". ");
  const contact = [ctx.brandStyle.website, ctx.brandStyle.contactPhone]
    .filter(Boolean)
    .join(", ");
  const fromCaption = (caption || "").replace(/\s+/g, " ").trim().slice(0, 280);
  const core = body || fromCaption || `${company} helps teams streamline document workflows.`;
  const closer = contact ? ` Learn more at ${contact}.` : ` Visit ${company} to learn more.`;
  return `${core}${closer}`.slice(0, 900);
}

/**
 * OpenAI TTS → MP3. Falls back to caller using silent audio when key/model fails.
 */
export async function synthesizeNarrationMp3(input: {
  text: string;
  outputPath: string;
}): Promise<{ ok: true; path: string } | { ok: false; error: string }> {
  const apiKey = process.env.OPENAI_API_KEY?.trim();
  if (!apiKey) return { ok: false, error: "OPENAI_API_KEY missing for video TTS" };

  const text = input.text.replace(/\s+/g, " ").trim();
  if (!text) return { ok: false, error: "Empty narration text" };

  try {
    const res = await fetch("https://api.openai.com/v1/audio/speech", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${apiKey}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        model: process.env.OPENAI_TTS_MODEL?.trim() || "tts-1",
        voice: process.env.OPENAI_TTS_VOICE?.trim() || "alloy",
        input: text.slice(0, 900),
        response_format: "mp3",
      }),
    });

    if (!res.ok) {
      const errText = await res.text().catch(() => "");
      return { ok: false, error: `OpenAI TTS ${res.status}: ${errText.slice(0, 200)}` };
    }

    const buf = Buffer.from(await res.arrayBuffer());
    await fs.writeFile(input.outputPath, buf);
    return { ok: true, path: input.outputPath };
  } catch (err) {
    return {
      ok: false,
      error: err instanceof Error ? err.message : "TTS request failed",
    };
  }
}

/** Generate a silent AAC/M4A bed of the given duration (always works with FFmpeg). */
export async function buildSilentAudio(input: {
  outputPath: string;
  durationSeconds: number;
}): Promise<{ ok: true; path: string } | { ok: false; error: string }> {
  const cfg = getVideoConfig();
  const duration = Math.max(1, input.durationSeconds);

  return new Promise((resolve) => {
    const args = [
      "-y",
      "-f",
      "lavfi",
      "-i",
      "anullsrc=channel_layout=stereo:sample_rate=44100",
      "-t",
      String(duration),
      "-c:a",
      "aac",
      "-b:a",
      "128k",
      input.outputPath,
    ];
    const proc = spawn(cfg.ffmpegPath, args, { stdio: ["ignore", "pipe", "pipe"] });
    let stderr = "";
    proc.stderr.on("data", (chunk: Buffer) => {
      stderr += chunk.toString();
    });
    proc.on("error", (err) => resolve({ ok: false, error: err.message }));
    proc.on("close", (code) => {
      if (code === 0) resolve({ ok: true, path: input.outputPath });
      else resolve({ ok: false, error: stderr.slice(-300) || `FFmpeg exited ${code}` });
    });
  });
}
