import OpenAI from "openai";

// the newest OpenAI model is "gpt-5" which was released August 7, 2025. do not change this unless explicitly requested by the user
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

// Memory for generated descriptions to avoid repetition
const generatedDescriptions = new Map<string, Set<string>>();

function getArtistFromTitle(title: string): string {
  // Extract artist name from title (everything before the first " - ")
  const match = title.match(/^([^-]+)/);
  return match ? match[1].trim() : "";
}

function addToMemory(artist: string, description: string) {
  if (!generatedDescriptions.has(artist)) {
    generatedDescriptions.set(artist, new Set());
  }
  generatedDescriptions.get(artist)!.add(description);
}

function getPreviousDescriptions(artist: string): string[] {
  return Array.from(generatedDescriptions.get(artist) || []);
}

export interface DescriptionGenerationOptions {
  maxCharacters?: number;
  language?: string;
  includeArtistInfo?: boolean;
  includeLabelInfo?: boolean;
  customInstructions?: string;
  contentType?: string;
}

export async function generateVideoDescription(
  title: string, 
  options: DescriptionGenerationOptions = {}
): Promise<string> {
  const {
    maxCharacters = 500,
    language = "slovenian",
    includeArtistInfo = true,
    includeLabelInfo = true,
    customInstructions = "",
    contentType = "music_video"
  } = options;

  try {
    // Extract artist name for memory checking
    const artist = getArtistFromTitle(title);
    const previousDescriptions = getPreviousDescriptions(artist);
    
    const avoidRepetition = previousDescriptions.length > 0 
      ? `\n\nWICHTIG: Für diesen Künstler wurden bereits folgende Beschreibungen erstellt:\n${previousDescriptions.map((desc, i) => `${i+1}. ${desc.substring(0, 100)}...`).join('\n')}\n\nErstelle eine VÖLLIG ANDERE Beschreibung mit anderen Worten, Fokus und Stil.`
      : '';

    // Determine content type specific instructions
    const isShow = contentType === 'oddaja';
    const contentTypeText = isShow ? 'Show/Sendung-Titel' : 'Musikvideo-Titel';
    const contentDescription = isShow 
      ? `WICHTIG: Dies ist eine TV-SENDUNG/SHOW (oddaja), NICHT ein Musikvideo!

Analysiere den Show-Titel und beschreibe:
- Die Show/Sendung und ihr Format
- Die Gastgeber oder Moderatoren
- Das Thema oder den Inhalt der Episode
- Für wen die Show gedacht ist (Zielgruppe)
- Art der Sendung (Talk-Show, Musiksendung, Unterhaltung, etc.)`
      : `Aus dem Titel extrahieren:
- Name des Interpreten/Künstlers
- Titel des Liedes/Stücks
- Art des Inhalts (Lied, Instrumental, Live-Auftritt, etc.)

Erstelle eine informative Beschreibung, die Folgendes beinhaltet:
${includeArtistInfo ? '- Informationen über den Interpreten (Musikstil, kurze Geschichte, bekannte Stücke)' : ''}
- Beschreibung des Musikstils und Genres
- Kurzer Hintergrund zum Stück, falls bekannt
- Wofür es gedacht ist (Tanz, Zuhören, Konzert, etc.)`;

    const prompt = `Analysiere diesen ${contentTypeText}: "${title}"

Schreibe auf DEUTSCH eine informative Beschreibung.

${contentDescription}

NUR wenn du SICHERE Informationen hast, erwähne:
${includeLabelInfo ? '- Label/Plattenfirma (nur wenn du es sicher weißt)' : ''}

Wenn du keine sicheren Informationen zu einem Punkt hast, lasse ihn WEG. Schreibe NIEMALS "Label unbekannt" oder ähnliches.

Die Beschreibung soll maximal ${maxCharacters} Zeichen lang sein.
Schreibe in einem freundlichen, informativen Ton.
${isShow ? 'Beschreibe die Show/Sendung, nicht die Musik.' : 'Verwende nicht die Wörter "Video" oder "Aufnahme" - schreibe über die Musik selbst.'}
${customInstructions ? `\nZUSÄTZLICHE ANWEISUNGEN: ${customInstructions}` : ''}
Schreibe nur die Beschreibung, keine zusätzlichen Erklärungen.${avoidRepetition}";`

    console.log("Sending request to OpenAI with title:", title); // Debug log
    
    const response = await openai.chat.completions.create({
      model: "gpt-4o", // Use gpt-4o instead of gpt-5 for better reliability
      messages: [
        {
          role: "system",
          content: `Du bist ein ${isShow ? 'Medien- und TV-Show-Experte' : 'Musikexperte'} und hilfst bei der Erstellung hochwertiger Beschreibungen für ${isShow ? 'TV-Sendungen und Shows' : 'Musikinhalte'}. Du antwortest immer auf Deutsch und vermeidest Wiederholungen.`
        },
        {
          role: "user", 
          content: prompt
        }
      ],
      max_tokens: Math.ceil(maxCharacters / 2), // Use max_tokens for gpt-4o
      temperature: 0.7, // gpt-4o supports temperature
    });
    
    console.log("OpenAI response received:", response.choices[0]?.message?.content); // Debug log

    const description = response.choices[0].message.content?.trim() || "";
    
    // Add to memory for this artist
    if (artist && description) {
      addToMemory(artist, description);
    }
    
    console.log("Generated description:", description); // Debug log
    
    // Ensure we don't exceed character limit
    if (description.length > maxCharacters) {
      return description.substring(0, maxCharacters - 3) + "...";
    }
    
    return description;
    
  } catch (error: any) {
    console.error("Error generating video description:", error);
    console.error("Error details:", error?.message || error); // More detailed error logging
    throw new Error("Fehler bei der KI-Beschreibungsgenerierung");
  }
}

export async function generateBulkDescriptions(
  videos: Array<{ id: string; title: string }>,
  options: DescriptionGenerationOptions = {}
): Promise<Array<{ id: string; description: string; error?: string }>> {
  const results = [];
  
  for (const video of videos) {
    try {
      const description = await generateVideoDescription(video.title, options);
      results.push({ id: video.id, description });
      
      // Add small delay to respect API rate limits
      await new Promise(resolve => setTimeout(resolve, 100));
    } catch (error) {
      results.push({ 
        id: video.id, 
        description: "", 
        error: error instanceof Error ? error.message : "Unknown error"
      });
    }
  }
  
  return results;
}