import fs from 'fs';
import path from 'path';
import { query } from './lib/mysql';
import { logger } from './lib/logger';
import { callLMStudio } from './lib/lmstudio';

async function main() {
  //await insertGenres();
  await generatePrompts();
  process.exit();
}

async function insertGenres() {
  logger.info('Starting genre insertion...');
  try {
    const genresPath = path.join(__dirname, 'data', 'genres.json');
    const genresData = JSON.parse(fs.readFileSync(genresPath, 'utf-8'));

    for (const genre in genresData) {
      if (genresData.hasOwnProperty(genre)) {
        const items = genresData[genre];
        for (let item of items) {
          if (Array.isArray(item)) {
            for (const subItem of item) {
              await processItem(genre, subItem);
            }
          } else {
            await processItem(genre, item);
          }
        }
      }
    }
    logger.info('Finished processing genres.');
  } catch (error) {
    logger.error('Error processing genres:', error);
  }
}

async function generatePrompts() {
  logger.info('Starting prompt generation...');
  try {
    const videosToUpdate = await query(
      'SELECT * FROM video WHERE image_prompt IS NULL OR video_prompt IS NULL'
    ) as any[];

    for (const video of videosToUpdate) {
      const prompt = `
        Based on the following video details, generate an image prompt and a video prompt.
        Each prompt should be around 100 words.
        The output should be a JSON object in the format: { "imagePrompt": "...", "videoPrompt": "..." }
        For video prompt, it takes  8 seconds. So start with current scene, describe action and camera work.
        Please include lighting details too.
        
        Details:
        - Genre: ${video.genre}
        - Sub-Genre: ${video.sub_genre}
        - Scene: ${video.scene}
        - Action: ${video.action}
        - Camera: ${video.camera}
      `;

      logger.info(`Generating prompt for video ID: ${video.id}`);
      logger.debug(prompt);

      let success = false;
      for (let i = 0; i < 10; i++) {
        try {
          const response = await callLMStudio(prompt);
          if (response && response.imagePrompt && response.videoPrompt) {
            await query(
              'UPDATE video SET image_prompt = ?, video_prompt = ? WHERE id = ?',
              [response.imagePrompt, response.videoPrompt, video.id]
            );
            logger.info(`Successfully updated prompts for video ID: ${video.id}`);
            success = true;
            break;
          }
        } catch (error) {
          logger.warn(`Attempt ${i + 1} failed for video ID ${video.id}:`, error);
        }
      }

      if (!success) {
        logger.error(`Failed to generate and parse prompts for video ID: ${video.id} after 10 attempts.`);
      }
    }
    logger.info('Finished generating prompts.');
  } catch (error) {
    logger.error('Error generating prompts:', error);
  }
}

async function processItem(genre: string, item: any) {
  if (item && typeof item === 'object' && !Array.isArray(item)) {
    const { subGenre, scene, action, camera } = item;

    // Check if the item already exists
    const existing = await query(
            'SELECT id FROM video WHERE genre = ? AND sub_genre = ? AND scene = ? AND action = ? AND camera = ?',
            [genre, subGenre, scene, action, camera]
          ) as any[];

    if (existing.length === 0) {
      // Insert the new item
      await query(
        'INSERT INTO video (genre, sub_genre, scene, action, camera) VALUES (?, ?, ?, ?, ?)',
        [genre, subGenre, scene, action, camera]
      );
      logger.info(`Inserted: ${genre} - ${subGenre} - ${scene}`);
    } else {
      logger.info(`Skipped (exists): ${genre} - ${subGenre} - ${scene}`);
    }
  }
}

main();
