const admin = require("firebase-admin");
const serviceAccount = require("./serviceAccountKey.json");
const { googleAI } = require("@genkit-ai/googleai");
const { GEMINI_API_KEY } = require("./config/keys");
const { genkit } = require("genkit");
const axios = require("axios");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  storageBucket: "musicland-d33f9.firebasestorage.app",
});

exports.generateAI = async ({ system = "", prompt = "", schema }) => {
  const genkitInstance = genkit({
    plugins: [
      googleAI({
        apiKey: GEMINI_API_KEY,
      }),
    ],
    model: googleAI.model("gemini-2.5-flash"),
  });

  if (prompt?.length < 1) {
    throw new Error(
      "Vous devez spécifier un prompt pour effectuer cette action.",
    );
  }

  const { output } = await genkitInstance.generate({
    system,
    prompt,
    output: { schema },
  });

  return output;
};

// Générateur d'images via appel direct REST Imagen 3.0 (retour base64 pur)
exports.generateImage = async ({ system = "", prompt = "" }) => {
  if (typeof prompt !== "string" || prompt.trim().length < 1) {
    throw new Error(
      "Vous devez spécifier un prompt pour effectuer cette action.",
    );
  }

  const baseUrl =
    "https://generativelanguage.googleapis.com/v1beta/models/imagen-3.0-generate-002:predict";
  const url = `${baseUrl}?key=${encodeURIComponent(GEMINI_API_KEY)}`;

  const mkBody = (p) => ({
    instances: [
      {
        prompt: p,
      },
    ],
    parameters: {
      sampleCount: 1,
      aspectRatio: "1:1",
      personGeneration: "dont_allow",
    },
  });

  const combinedPrompt = [
    system,
    "Contraintes supplémentaires: pas de personnes, pas de visages, style abstrait, formes géométriques, textures et motifs.",
    prompt,
  ]
    .filter(Boolean)
    .join("\n\n");

  const tryOnce = async (p) => {
    const resp = await axios.post(url, mkBody(p), {
      headers: { "Content-Type": "application/json" },
      timeout: 120000,
    });
    const predictions = resp?.data?.predictions || [];
    const first = predictions.find((x) => x?.bytesBase64Encoded);
    return first
      ? {
          b64: first.bytesBase64Encoded,
          mimeType: first.mimeType || "image/png",
        }
      : { b64: "", mimeType: null };
  };

  // Primary try
  let result = { b64: "", mimeType: null };
  try {
    result = await tryOnce(combinedPrompt);
  } catch (e) {
    const em = e?.response?.data || e?.message || e;
    console.error("Imagen predict error", em);
  }

  // Fallbacks on safety filters/no predictions
  if (!result?.b64) {
    const fallback = [
      "Crée une image de pochette d'album 1024x1024, abstraite, moderne et colorée.",
      "Utilise des formes géométriques, textures et dégradés.",
      "Aucune personne, aucun visage, aucun texte, aucun logo.",
    ].join("\n");
    try {
      result = await tryOnce(fallback);
    } catch (e2) {
      const em2 = e2?.response?.data || e2?.message || e2;
      console.error("Imagen predict fallback FR error", em2);
    }
  }

  if (!result?.b64) {
    const fallbackEn = [
      "Create a 1024x1024 abstract, modern, colorful album cover.",
      "Use geometric shapes, textures, and gradients.",
      "No people, no faces, no text, no logos.",
    ].join("\n");
    try {
      result = await tryOnce(fallbackEn);
    } catch (e3) {
      const em3 = e3?.response?.data || e3?.message || e3;
      console.error("Imagen predict fallback EN error", em3);
    }
  }

  if (!result?.b64) {
    throw new Error("NO_IMAGE_OUTPUT");
  }
  return {
    b64: String(result.b64).trim(),
    mimeType: result.mimeType || "image/png",
  };
};

// Exporter toutes les fonctions
exports.music = require("./src/music");
exports.lyrics = require("./src/lyrics");
exports.cover = require("./src/cover");
