/**
 * Audio Content AI Context Routes
 *
 * 3-Step Generation Workflow:
 * Step 1: POST /generate-content — Generate lyrics/content with AI
 * Step 2: POST /generate-prompt — Generate optimized Suno prompt from edited lyrics
 * Step 3: POST /generate-song — Submit to Suno API for audio generation
 *
 * Legacy:
 * POST /regenerate — Re-generate song with existing prompt
 * GET /status/:jobId — Check job status
 */

import express, { Request, Response } from 'express';
import { body, validationResult } from 'express-validator';
import { authenticate } from '../middleware/auth';
import { requirePermission } from '../middleware/permissions';
import { getModels } from '../models';
import {
  createJob,
  updateJobProgress,
  completeJob,
  failJob,
  getJob,
  AiJob,
} from '../services/aiContext/aiJobManager';
import { AudioContentPipeline } from '../services/aiContext/audioContentPipeline';
import { AudioContentPromptPipeline } from '../services/aiContext/audioContentPipeline';
import { AudioContentPipelineInputs, AudioContentPromptInputs } from '../services/aiContext/audioContentPrompts';
import {
  createSunoGeneration,
  pollSunoGeneration,
  SunoError,
} from '../services/sunoService';
import { aiContextService } from '../services/aiContext/aiContextService';

const router = express.Router();

// ============================================
// HELPER: Map Suno/pipeline errors to user-friendly messages
// ============================================

function getUserFriendlyError(error: any): string {
  if (error instanceof SunoError) {
    switch (error.errorType) {
      case 'auth_error':
        return 'Audio service authentication failed. Please try again later.';
      case 'rate_limit':
        return 'Too many requests to the audio service. Please wait a moment and try again.';
      case 'timeout':
        return 'Audio content generation timed out. Please try again.';
      case 'provider_error':
        return 'The audio service is temporarily unavailable. Please try again later.';
      case 'network_error':
        return 'Network error connecting to the audio service. Please check your connection and try again.';
      default:
        return error.message;
    }
  }
  if (error.message?.includes('duplicate')) {
    return 'A generation is already in progress for this content. Please wait for it to complete.';
  }
  return error.message || 'An unexpected error occurred during audio content generation.';
}

// ============================================
// HELPER: Load company context for pipeline inputs
// ============================================

async function loadCompanyContext(companyId: string): Promise<Partial<AudioContentPipelineInputs & AudioContentPromptInputs>> {
  const context: Partial<AudioContentPipelineInputs & AudioContentPromptInputs> = {};

  try {
    const { Company, ICP, Brand, Product } = getModels();
    const company = await Company.findOne({ _id: companyId });
    if (company) {
      context.companyName = company.name || '';
      context.companyDescription = company.description || company.about || '';
      context.companyIndustry = company.industry || '';
      context.companyBusinessModel = company.businessModel || '';
      context.companyTargetAudience = company.targetAudience || '';
      context.companyPrimaryOffering = company.primaryOffering || '';
      context.companyUsps = company.usps || [];
    }

    const icp = await ICP.findOne({ companyId });
    if (icp) {
      context.icpName = icp.name || '';
      context.icpIndustry = icp.industry || '';
      context.icpCompanySize = icp.companySize || '';
      context.icpPainPoints = icp.painPoints || [];
      context.icpBusinessGoals = icp.businessGoals || [];
    }

    const brand = await Brand.findOne({ companyId });
    if (brand) {
      context.brandArchetype = brand.archetype || '';
      context.brandPersonality = brand.personality || [];
      context.brandValues = brand.values || [];
      context.brandPositioning = brand.positioning || '';
      context.brandVoice = brand.voice || '';
    }

    const products = await Product.find({ companyId });
    if (products.length > 0) {
      context.productNames = products.map((p: any) => p.name);
      context.productDescriptions = products.map((p: any) => p.description || '');
    }
  } catch (ctxError: any) {
    console.warn('[AudioContent] Could not load full company context:', ctxError.message);
  }

  return context;
}

// ============================================
// STEP 1: POST /generate-content — Generate lyrics/content
// ============================================

router.post('/generate-content', [
  authenticate,
  requirePermission('audio-content', 'ai-generate'),
  body('companyId').notEmpty().withMessage('Company ID is required'),
  body('songTitle').notEmpty().withMessage('Song title is required'),
], async (req: Request, res: Response) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    res.status(400).json({ error: 'Validation failed', details: errors.array() });
    return;
  }

  try {
    const { companyId, songTitle, topic, description, prompt, genre, mood, language, singerType, duration, instrumentStyle, negativePrompt, customInstructions, targetAudience, preferredProvider, preferredModel, providerLock } = req.body;
    const userId = (req as any).user?.id;

    // Verify company ownership
    if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied: You do not belong to this company' });
      return;
    }

    // Create AI job
    const job = createJob('audio-content', companyId, 'audio-content-generate-content');
    updateJobProgress(job.jobId, 5, 'Starting content generation...');

    // Return 202 with job ID immediately
    res.status(202).json({ jobId: job.jobId, status: 'processing' });

    // Run pipeline asynchronously
    setImmediate(async () => {
      try {
        // Load company context
        const context = await loadCompanyContext(companyId);

        // Build pipeline inputs
        const pipelineInputs: AudioContentPipelineInputs = {
          songTitle,
          topic,
          description,
          prompt,
          genre,
          mood,
          language,
          singerType,
          duration,
          instrumentStyle,
          negativePrompt,
          targetAudience,
          customInstructions,
          companyName: context.companyName || '',
          companyDescription: context.companyDescription,
          companyIndustry: context.companyIndustry,
          companyBusinessModel: context.companyBusinessModel,
          companyTargetAudience: context.companyTargetAudience,
          companyPrimaryOffering: context.companyPrimaryOffering,
          companyUsps: context.companyUsps,
          icpName: context.icpName,
          icpIndustry: context.icpIndustry,
          icpCompanySize: context.icpCompanySize,
          icpPainPoints: context.icpPainPoints,
          icpBusinessGoals: context.icpBusinessGoals,
          brandArchetype: context.brandArchetype,
          brandPersonality: context.brandPersonality,
          brandValues: context.brandValues,
          brandPositioning: context.brandPositioning,
          brandVoice: context.brandVoice,
          productNames: context.productNames,
          productDescriptions: context.productDescriptions,
        };

        updateJobProgress(job.jobId, 10, 'Generating song content with AI...');

        const pipeline = new AudioContentPipeline(
          pipelineInputs,
          companyId,
          'audio-content',
          preferredProvider || 'auto',
          preferredModel || '',
          providerLock || false
        );

        pipeline.onProgress = (progress: number, step: string) => {
          updateJobProgress(job.jobId, Math.min(progress, 89), step);
        };

        const result = await pipeline.run();

        if (result.errors.length > 0 && !result.lyrics) {
          // Pipeline returned partial results but no usable content — save as failed
          const errorMsg = `Content generation failed: ${result.errors.join('; ')}`;

          try {
            const failedRecord = await aiContextService.create({
              companyId,
              moduleSource: 'audio-content',
              analysisType: 'audio-content-generate-content',
              inputs: {
                companyName: context.companyName || '',
                songTitle,
                topic: topic || '',
                genre: genre || '',
                mood: mood || '',
              } as any,
              analysis: {} as any,
              metadata: {
                pipelineVersion: result.pipelineVersion,
                provider: result.provider || 'unknown',
                model: result.aiModel || 'unknown',
                tokensUsed: result.tokensUsed || 0,
                inputTokens: result.inputTokens || 0,
                outputTokens: result.outputTokens || 0,
                processingTimeMs: result.processingTimeMs || 0,
                latencyMs: result.latencyMs || 0,
                overallConfidence: 0,
                fieldConfidences: {},
                finishReason: 'error',
                error: errorMsg,
              },
            });
            await aiContextService.updateStatus(failedRecord.id, 'rejected');
          } catch (ctxErr: any) {
            console.warn(`[AudioContent-GenerateContent] AiContext failed-record save failed (non-fatal): ${ctxErr.message}`);
          }

          throw new Error(errorMsg);
        }

        // Complete job with lyrics result data
        completeJob(job.jobId, {
          songTitle: result.songTitle,
          songConcept: result.songConcept,
          lyrics: result.lyrics,
          chorus: result.chorus,
          verses: result.verses,
          bridge: result.bridge,
          genreSuggestions: result.genreSuggestions,
          mood: result.mood,
          musicTags: result.musicTags,
          // Pass AI metadata so the frontend can forward it to Step 3
          _aiMeta: {
            provider: result.provider,
            aiModel: result.aiModel,
            tokensUsed: result.tokensUsed,
            inputTokens: result.inputTokens,
            outputTokens: result.outputTokens,
            processingTimeMs: result.processingTimeMs,
            latencyMs: result.latencyMs,
            overallConfidence: result.overallConfidence,
            pipelineVersion: result.pipelineVersion,
            finishReason: result.finishReason,
            apiKeyMasked: result.apiKeyMasked,
          },
        }, 'audio-content');

        // Save AI metadata to AiContext for the AI Processing dashboard
        try {
          const aiContextRecord = await aiContextService.create({
            companyId,
            moduleSource: 'audio-content',
            analysisType: 'audio-content-generate-content',
            inputs: {
              companyName: context.companyName || '',
              songTitle,
              topic: topic || '',
              genre: genre || '',
              mood: mood || '',
            } as any,
            analysis: {
              songTitle: result.songTitle,
              songConcept: result.songConcept,
              lyrics: result.lyrics,
              chorus: result.chorus,
              verses: result.verses,
              bridge: result.bridge,
              genreSuggestions: result.genreSuggestions,
              mood: result.mood,
              musicTags: result.musicTags,
            } as any,
            metadata: {
              pipelineVersion: result.pipelineVersion,
              provider: result.provider,
              model: result.aiModel,
              tokensUsed: result.tokensUsed,
              inputTokens: result.inputTokens,
              outputTokens: result.outputTokens,
              processingTimeMs: result.processingTimeMs,
              latencyMs: result.latencyMs,
              overallConfidence: Math.round(result.overallConfidence * 100),
              fieldConfidences: {},
              finishReason: result.finishReason,
              apiKeyMasked: result.apiKeyMasked,
            },
          });
          await aiContextService.updateStatus(aiContextRecord.id, 'approved');
        } catch (ctxErr: any) {
          console.warn(`[AudioContent-GenerateContent] AiContext save failed (non-fatal): ${ctxErr.message}`);
        }

      } catch (error: any) {
        console.error('[AudioContent] Content generation error:', error);

        // Save failed generation to AiContext so it appears in AI Processing dashboard
        try {
          const failedRecord = await aiContextService.create({
            companyId,
            moduleSource: 'audio-content',
            analysisType: 'audio-content-generate-content',
            inputs: {
              songTitle,
              topic: topic || '',
              genre: genre || '',
              mood: mood || '',
            } as any,
            analysis: {} as any,
            metadata: {
              pipelineVersion: '2.0',
              provider: 'unknown',
              model: 'unknown',
              tokensUsed: 0,
              inputTokens: 0,
              outputTokens: 0,
              processingTimeMs: 0,
              overallConfidence: 0,
              fieldConfidences: {},
              finishReason: 'error',
              error: error.message || 'Content generation failed',
            },
          });
          await aiContextService.updateStatus(failedRecord.id, 'rejected');
        } catch (ctxErr: any) {
          console.warn(`[AudioContent-GenerateContent] AiContext failed-record save failed (non-fatal): ${ctxErr.message}`);
        }

        failJob(job.jobId, getUserFriendlyError(error));
      }
    });

  } catch (error: any) {
    console.error('Error starting content generation:', error);
    res.status(500).json({ error: 'Failed to start content generation', details: error.message });
  }
});

// ============================================
// STEP 2: POST /generate-prompt — Generate optimized Suno prompt
// ============================================

router.post('/generate-prompt', [
  authenticate,
  requirePermission('audio-content', 'ai-generate'),
  body('companyId').notEmpty().withMessage('Company ID is required'),
], async (req: Request, res: Response) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    res.status(400).json({ error: 'Validation failed', details: errors.array() });
    return;
  }

  try {
    const { companyId, lyrics, songTitle, topic, prompt, genre, mood, language, singerType, duration, instrumentStyle, negativePrompt, songConcept, chorus, verses, bridge, preferredProvider, preferredModel, providerLock } = req.body;

    // Verify company ownership
    if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied: You do not belong to this company' });
      return;
    }

    // Create AI job
    const job = createJob('audio-content', companyId, 'audio-content-generate-prompt');
    updateJobProgress(job.jobId, 5, 'Starting prompt generation...');

    // Return 202 with job ID immediately
    res.status(202).json({ jobId: job.jobId, status: 'processing' });

    // Run pipeline asynchronously
    setImmediate(async () => {
      try {
        // Load company context
        const context = await loadCompanyContext(companyId);

        // Build prompt inputs
        const promptInputs: AudioContentPromptInputs = {
          lyrics,
          songTitle,
          topic,
          prompt,
          genre,
          mood,
          language,
          singerType,
          duration,
          instrumentStyle,
          negativePrompt,
          songConcept,
          chorus,
          verses,
          bridge,
          companyName: context.companyName,
          companyDescription: context.companyDescription,
          companyIndustry: context.companyIndustry,
          companyBusinessModel: context.companyBusinessModel,
          companyTargetAudience: context.companyTargetAudience,
          companyPrimaryOffering: context.companyPrimaryOffering,
          companyUsps: context.companyUsps,
          brandArchetype: context.brandArchetype,
          brandPersonality: context.brandPersonality,
          brandValues: context.brandValues,
          brandPositioning: context.brandPositioning,
          brandVoice: context.brandVoice,
          productNames: context.productNames,
          productDescriptions: context.productDescriptions,
        };

        updateJobProgress(job.jobId, 10, 'Generating optimized Suno prompt...');

        const pipeline = new AudioContentPromptPipeline(
          promptInputs,
          companyId,
          'audio-content',
          preferredProvider || 'auto',
          preferredModel || '',
          providerLock || false
        );

        pipeline.onProgress = (progress: number, step: string) => {
          updateJobProgress(job.jobId, Math.min(progress, 89), step);
        };

        const result = await pipeline.run();

        if (result.errors.length > 0 && !result.optimizedSunoPrompt) {
          // Pipeline returned partial results but no usable prompt — save as failed
          const errorMsg = `Prompt generation failed: ${result.errors.join('; ')}`;

          try {
            const failedRecord = await aiContextService.create({
              companyId,
              moduleSource: 'audio-content',
              analysisType: 'audio-content-generate-prompt',
              inputs: {
                companyName: context.companyName || '',
                songTitle: songTitle || '',
              } as any,
              analysis: {} as any,
              metadata: {
                pipelineVersion: result.pipelineVersion,
                provider: result.provider || 'unknown',
                model: result.aiModel || 'unknown',
                tokensUsed: result.tokensUsed || 0,
                inputTokens: result.inputTokens || 0,
                outputTokens: result.outputTokens || 0,
                processingTimeMs: result.processingTimeMs || 0,
                latencyMs: result.latencyMs || 0,
                overallConfidence: 0,
                fieldConfidences: {},
                finishReason: 'error',
                error: errorMsg,
              },
            });
            await aiContextService.updateStatus(failedRecord.id, 'rejected');
          } catch (ctxErr: any) {
            console.warn(`[AudioContent-GeneratePrompt] AiContext failed-record save failed (non-fatal): ${ctxErr.message}`);
          }

          throw new Error(errorMsg);
        }

        // Complete job with prompt result data
        completeJob(job.jobId, {
          optimizedSunoPrompt: result.optimizedSunoPrompt,
          suggestedTags: result.suggestedTags,
          confidence: result.confidence,
          // Pass AI metadata so the frontend can forward it to Step 3
          _aiMeta: {
            provider: result.provider,
            aiModel: result.aiModel,
            tokensUsed: result.tokensUsed,
            inputTokens: result.inputTokens,
            outputTokens: result.outputTokens,
            processingTimeMs: result.processingTimeMs,
            latencyMs: result.latencyMs,
            overallConfidence: result.overallConfidence,
            pipelineVersion: result.pipelineVersion,
            finishReason: result.finishReason,
            apiKeyMasked: result.apiKeyMasked,
          },
        }, 'audio-content');

        // Save AI metadata to AiContext for the AI Processing dashboard
        try {
          const aiContextRecord = await aiContextService.create({
            companyId,
            moduleSource: 'audio-content',
            analysisType: 'audio-content-generate-prompt',
            inputs: {
              companyName: context.companyName || '',
              songTitle: songTitle || '',
            } as any,
            analysis: {
              optimizedSunoPrompt: result.optimizedSunoPrompt,
              suggestedTags: result.suggestedTags,
            } as any,
            metadata: {
              pipelineVersion: result.pipelineVersion,
              provider: result.provider,
              model: result.aiModel,
              tokensUsed: result.tokensUsed,
              inputTokens: result.inputTokens,
              outputTokens: result.outputTokens,
              processingTimeMs: result.processingTimeMs,
              latencyMs: result.latencyMs,
              overallConfidence: Math.round(result.overallConfidence * 100),
              fieldConfidences: {},
              finishReason: result.finishReason,
              apiKeyMasked: result.apiKeyMasked,
            },
          });
          await aiContextService.updateStatus(aiContextRecord.id, 'approved');
        } catch (ctxErr: any) {
          console.warn(`[AudioContent-GeneratePrompt] AiContext save failed (non-fatal): ${ctxErr.message}`);
        }

      } catch (error: any) {
        console.error('[AudioContent] Prompt generation error:', error);

        // Save failed generation to AiContext so it appears in AI Processing dashboard
        try {
          const failedRecord = await aiContextService.create({
            companyId,
            moduleSource: 'audio-content',
            analysisType: 'audio-content-generate-prompt',
            inputs: {
              songTitle: songTitle || '',
            } as any,
            analysis: {} as any,
            metadata: {
              pipelineVersion: '2.0',
              provider: 'unknown',
              model: 'unknown',
              tokensUsed: 0,
              inputTokens: 0,
              outputTokens: 0,
              processingTimeMs: 0,
              overallConfidence: 0,
              fieldConfidences: {},
              finishReason: 'error',
              error: error.message || 'Prompt generation failed',
            },
          });
          await aiContextService.updateStatus(failedRecord.id, 'rejected');
        } catch (ctxErr: any) {
          console.warn(`[AudioContent-GeneratePrompt] AiContext failed-record save failed (non-fatal): ${ctxErr.message}`);
        }

        failJob(job.jobId, getUserFriendlyError(error));
      }
    });

  } catch (error: any) {
    console.error('Error starting prompt generation:', error);
    res.status(500).json({ error: 'Failed to start prompt generation', details: error.message });
  }
});

// ============================================
// STEP 3: POST /generate-song — Generate song via Suno
// ============================================

router.post('/generate-song', [
  authenticate,
  requirePermission('audio-content', 'ai-generate'),
  body('companyId').notEmpty().withMessage('Company ID is required'),
  body('songTitle').notEmpty().withMessage('Song title is required'),
  body('optimizedSunoPrompt').notEmpty().withMessage('Suno prompt is required'),
], async (req: Request, res: Response) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    res.status(400).json({ error: 'Validation failed', details: errors.array() });
    return;
  }

  try {
    const {
      companyId, songTitle, optimizedSunoPrompt,
      lyrics, genre, mood, language, singerType, duration, instrumentStyle, negativePrompt,
      topic, description, targetAudience,
      songConcept, generatedChorus, generatedVerses, generatedBridge,
      generatedGenreSuggestions, generatedMood, generatedMusicTags,
    } = req.body;
    const userId = (req as any).user?.id;

    // Verify company ownership
    if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied: You do not belong to this company' });
      return;
    }

    // Duplicate prevention: check for existing processing jobs
    const { AudioContent } = getModels();
    const existingActive = await AudioContent.findOne({
      companyId,
      status: 'processing',
    }).limit(1);

    if (existingActive) {
      res.status(409).json({
        error: 'A generation is already in progress for this company. Please wait for it to complete before starting a new one.',
      });
      return;
    }

    // Create AudioContent document in MongoDB
    const audioContent = new AudioContent({
      companyId,
      songTitle,
      prompt: lyrics || optimizedSunoPrompt, // Use lyrics as prompt, fallback to Suno prompt
      genre: genre || (generatedGenreSuggestions?.[0]) || undefined,
      mood: mood || generatedMood || undefined,
      language: language || 'en',
      singerType: singerType || undefined,
      duration: duration ? Number(duration) : undefined,
      instrumentStyle: instrumentStyle || undefined,
      negativePrompt: negativePrompt || undefined,

      // User-input fields
      topic: topic || undefined,
      description: description || undefined,
      targetAudience: targetAudience || undefined,

      // AI-generated fields (from Steps 1 & 2)
      generatedLyrics: lyrics || undefined,
      songConcept: songConcept || undefined,
      generatedChorus: generatedChorus || undefined,
      generatedVerses: generatedVerses || undefined,
      generatedBridge: generatedBridge || undefined,
      generatedGenreSuggestions: generatedGenreSuggestions || undefined,
      generatedMood: generatedMood || undefined,
      generatedMusicTags: generatedMusicTags || undefined,
      optimizedSunoPrompt,

      // AI context
      aiGenerated: true,
      aiGenerationContext: {
        pipelineVersion: '2.0',
        generatedAt: new Date(),
      },

      // Audit
      createdBy: userId || undefined,

      status: 'processing',
      isFavorite: false,
      tags: generatedMusicTags || [],
    });

    await audioContent.save();

    // Create AI job
    const job = createJob('audio-content', companyId, 'audio-content-generate-song');
    updateJobProgress(job.jobId, 5, 'Starting Suno audio generation...');

    // Return 202 with job ID immediately
    res.status(202).json({ jobId: job.jobId, status: 'processing' });

    // Run Suno generation asynchronously
    setImmediate(async () => {
      const songStartTime = Date.now();
      try {
        updateJobProgress(job.jobId, 10, 'Submitting to Suno AI for audio generation...');

        const sunoResult = await createSunoGeneration({
          prompt: optimizedSunoPrompt,
          title: songTitle,
          genre: genre || generatedGenreSuggestions?.[0],
          mood: mood || generatedMood,
          ...(duration ? { duration: Number(duration) || undefined } : {}),
          negativePrompt: negativePrompt || undefined,
          makeInstrumental: singerType === 'instrumental',
        });

        // Update document with Suno job ID
        audioContent.providerJobId = sunoResult.jobId;
        audioContent.providerStatus = 'processing';
        await audioContent.save();

        updateJobProgress(job.jobId, 20, 'Waiting for Suno AI audio generation...');

        // Poll Suno for completion
        const finalSunoResult = await pollSunoGeneration(sunoResult.jobId);

        if (finalSunoResult.status === 'completed') {
          // Update document with completed data
          audioContent.providerStatus = 'completed';
          audioContent.audioUrl = finalSunoResult.audioUrl;
          audioContent.coverImageUrl = finalSunoResult.coverImageUrl;
          audioContent.providerMetadata = {
            ...finalSunoResult.metadata,
            provider: 'suno',
          };

          if (finalSunoResult.lyrics && !audioContent.generatedLyrics) {
            audioContent.generatedLyrics = finalSunoResult.lyrics;
          }
          if (finalSunoResult.duration) {
            audioContent.duration = finalSunoResult.duration;
          }

          // Update AI generation context with Suno metadata
          audioContent.aiGenerationContext = {
            ...audioContent.aiGenerationContext,
            provider: 'suno',
            model: finalSunoResult.metadata?.model || 'suno',
          };

          audioContent.status = 'completed';
          await audioContent.save();

          // Save Suno generation to AiContext for the AI Processing dashboard
          try {
            const songProcessingTimeMs = Date.now() - songStartTime;
            const sunoContext = await aiContextService.create({
              companyId,
              moduleSource: 'audio-content',
              analysisType: 'audio-content-generate-song',
              inputs: { songTitle, optimizedSunoPrompt } as any,
              analysis: { audioUrl: audioContent.audioUrl, coverImageUrl: audioContent.coverImageUrl, status: 'completed' } as any,
              metadata: {
                pipelineVersion: '2.0',
                provider: 'suno',
                model: finalSunoResult.metadata?.model || 'suno',
                tokensUsed: 0,
                processingTimeMs: songProcessingTimeMs,
                overallConfidence: 0,
                fieldConfidences: {},
                finishReason: 'completed',
              },
            });
            await aiContextService.updateStatus(sunoContext.id, 'approved');
          } catch (ctxErr: any) {
            console.warn(`[AudioContent-GenerateSong] AiContext save failed (non-fatal): ${ctxErr.message}`);
          }

          completeJob(job.jobId, {
            _id: audioContent._id,
            songTitle: audioContent.songTitle,
            status: 'completed',
            audioUrl: audioContent.audioUrl,
            coverImageUrl: audioContent.coverImageUrl,
            generatedLyrics: audioContent.generatedLyrics,
            optimizedSunoPrompt: audioContent.optimizedSunoPrompt,
          }, 'audio-content');

        } else {
          // Suno generation failed
          audioContent.providerStatus = 'failed';
          audioContent.status = 'failed';
          await audioContent.save();

          const errorMsg = finalSunoResult.error || 'Suno audio content generation failed';
          const songProcessingTimeMs = Date.now() - songStartTime;

          // Save failed Suno generation to AiContext for the AI Processing dashboard
          try {
            const failedRecord = await aiContextService.create({
              companyId,
              moduleSource: 'audio-content',
              analysisType: 'audio-content-generate-song',
              inputs: { songTitle, optimizedSunoPrompt } as any,
              analysis: {} as any,
              metadata: {
                pipelineVersion: '2.0',
                provider: 'suno',
                model: finalSunoResult.metadata?.model || 'suno',
                tokensUsed: 0,
                processingTimeMs: songProcessingTimeMs,
                overallConfidence: 0,
                fieldConfidences: {},
                finishReason: 'error',
                error: errorMsg,
              },
            });
            await aiContextService.updateStatus(failedRecord.id, 'rejected');
          } catch (ctxErr: any) {
            console.warn(`[AudioContent-GenerateSong] AiContext failed-record save failed (non-fatal): ${ctxErr.message}`);
          }

          failJob(job.jobId, getUserFriendlyError(new Error(errorMsg)));
        }

      } catch (sunoError: any) {
        console.error('[AudioContent] Suno API error:', sunoError.message);

        audioContent.providerStatus = 'failed';
        audioContent.status = 'failed';
        await audioContent.save();

        const songProcessingTimeMs = Date.now() - songStartTime;

        // Save failed Suno generation to AiContext for the AI Processing dashboard
        try {
          const failedRecord = await aiContextService.create({
            companyId,
            moduleSource: 'audio-content',
            analysisType: 'audio-content-generate-song',
            inputs: { songTitle, optimizedSunoPrompt } as any,
            analysis: {} as any,
            metadata: {
              pipelineVersion: '2.0',
              provider: 'suno',
              model: 'suno',
              tokensUsed: 0,
              processingTimeMs: songProcessingTimeMs,
              overallConfidence: 0,
              fieldConfidences: {},
              finishReason: 'error',
              error: sunoError.message || 'Suno API error',
            },
          });
          await aiContextService.updateStatus(failedRecord.id, 'rejected');
        } catch (ctxErr: any) {
          console.warn(`[AudioContent-GenerateSong] AiContext failed-record save failed (non-fatal): ${ctxErr.message}`);
        }

        failJob(job.jobId, getUserFriendlyError(sunoError));
      }
    });

  } catch (error: any) {
    console.error('Error starting song generation:', error);
    res.status(500).json({ error: 'Failed to start song generation', details: error.message });
  }
});

// ============================================
// POST /regenerate — Regenerate song with existing prompt
// ============================================

router.post('/regenerate', [
  authenticate,
  requirePermission('audio-content', 'ai-generate'),
  body('companyId').notEmpty().withMessage('Company ID is required'),
], async (req: Request, res: Response) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    res.status(400).json({ error: 'Validation failed', details: errors.array() });
    return;
  }

  try {
    const { companyId, audioContentId } = req.body;
    const userId = (req as any).user?.id;

    // Verify company ownership
    if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied: You do not belong to this company' });
      return;
    }

    // If audioContentId provided, re-generate with existing prompt
    if (audioContentId) {
      const { AudioContent } = getModels();
      const existing = await AudioContent.findOne({ _id: audioContentId, companyId });
      if (!existing) {
        res.status(404).json({ error: 'Audio content not found' });
        return;
      }

      if (!existing.optimizedSunoPrompt) {
        res.status(400).json({ error: 'Cannot regenerate: no Suno prompt found for this content' });
        return;
      }

      // Duplicate prevention
      const existingActive = await AudioContent.findOne({
        companyId,
        status: 'processing',
      }).limit(1);

      if (existingActive) {
        res.status(409).json({
          error: 'A generation is already in progress for this company. Please wait for it to complete.',
        });
        return;
      }

      // Create new AudioContent document with same data
      const audioContent = new AudioContent({
        companyId,
        songTitle: existing.songTitle,
        prompt: existing.prompt,
        genre: existing.genre,
        mood: existing.mood,
        language: existing.language,
        singerType: existing.singerType,
        duration: existing.duration,
        instrumentStyle: existing.instrumentStyle,
        negativePrompt: existing.negativePrompt,
        topic: existing.topic,
        description: existing.description,
        targetAudience: existing.targetAudience,
        generatedLyrics: existing.generatedLyrics,
        songConcept: existing.songConcept,
        generatedChorus: existing.generatedChorus,
        generatedVerses: existing.generatedVerses,
        generatedBridge: existing.generatedBridge,
        generatedGenreSuggestions: existing.generatedGenreSuggestions,
        generatedMood: existing.generatedMood,
        generatedMusicTags: existing.generatedMusicTags,
        optimizedSunoPrompt: existing.optimizedSunoPrompt,
        aiGenerated: true,
        aiGenerationContext: existing.aiGenerationContext,
        createdBy: userId || undefined,
        status: 'processing',
        isFavorite: false,
        tags: existing.tags || [],
      });

      await audioContent.save();

      const job = createJob('audio-content', companyId, 'audio-content-generate-song');
      updateJobProgress(job.jobId, 5, 'Starting song regeneration...');

      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        const regenStartTime = Date.now();
        try {
          updateJobProgress(job.jobId, 10, 'Submitting to Suno AI for song regeneration...');

          const sunoResult = await createSunoGeneration({
            prompt: existing.optimizedSunoPrompt,
            title: existing.songTitle,
            genre: existing.genre || undefined,
            mood: existing.mood || undefined,
            ...(existing.duration ? { duration: existing.duration } : {}),
            negativePrompt: existing.negativePrompt || undefined,
            makeInstrumental: existing.singerType === 'instrumental',
          });

          audioContent.providerJobId = sunoResult.jobId;
          audioContent.providerStatus = 'processing';
          await audioContent.save();

          updateJobProgress(job.jobId, 20, 'Waiting for Suno AI song regeneration...');

          const finalSunoResult = await pollSunoGeneration(sunoResult.jobId);

          if (finalSunoResult.status === 'completed') {
            audioContent.providerStatus = 'completed';
            audioContent.audioUrl = finalSunoResult.audioUrl;
            audioContent.coverImageUrl = finalSunoResult.coverImageUrl;
            audioContent.providerMetadata = { ...finalSunoResult.metadata, provider: 'suno' };

            if (finalSunoResult.lyrics && !audioContent.generatedLyrics) {
              audioContent.generatedLyrics = finalSunoResult.lyrics;
            }
            if (finalSunoResult.duration) {
              audioContent.duration = finalSunoResult.duration;
            }

            audioContent.aiGenerationContext = {
              ...audioContent.aiGenerationContext,
              provider: 'suno',
              model: finalSunoResult.metadata?.model || 'suno',
            };

            audioContent.status = 'completed';
            await audioContent.save();

            // Save Suno regeneration to AiContext for the AI Processing dashboard
            try {
              const regenProcessingTimeMs = Date.now() - regenStartTime;
              const sunoContext = await aiContextService.create({
                companyId,
                moduleSource: 'audio-content',
                analysisType: 'audio-content-regenerate',
                inputs: { songTitle: existing.songTitle } as any,
                analysis: { audioUrl: audioContent.audioUrl, coverImageUrl: audioContent.coverImageUrl, status: 'completed' } as any,
                metadata: {
                  pipelineVersion: '2.0',
                  provider: 'suno',
                  model: finalSunoResult.metadata?.model || 'suno',
                  tokensUsed: 0,
                  processingTimeMs: regenProcessingTimeMs,
                  overallConfidence: 0,
                  fieldConfidences: {},
                  finishReason: 'completed',
                },
              });
              await aiContextService.updateStatus(sunoContext.id, 'approved');
            } catch (ctxErr: any) {
              console.warn(`[AudioContent-Regenerate] AiContext save failed (non-fatal): ${ctxErr.message}`);
            }

            completeJob(job.jobId, {
              _id: audioContent._id,
              songTitle: audioContent.songTitle,
              status: 'completed',
              audioUrl: audioContent.audioUrl,
              coverImageUrl: audioContent.coverImageUrl,
              generatedLyrics: audioContent.generatedLyrics,
              optimizedSunoPrompt: audioContent.optimizedSunoPrompt,
            }, 'audio-content');
          } else {
            audioContent.providerStatus = 'failed';
            audioContent.status = 'failed';
            await audioContent.save();

            const errorMsg = finalSunoResult.error || 'Suno song regeneration failed';
            const regenProcessingTimeMs = Date.now() - regenStartTime;

            // Save failed Suno regeneration to AiContext for the AI Processing dashboard
            try {
              const failedRecord = await aiContextService.create({
                companyId,
                moduleSource: 'audio-content',
                analysisType: 'audio-content-regenerate',
                inputs: { songTitle: existing.songTitle } as any,
                analysis: {} as any,
                metadata: {
                  pipelineVersion: '2.0',
                  provider: 'suno',
                  model: finalSunoResult.metadata?.model || 'suno',
                  tokensUsed: 0,
                  processingTimeMs: regenProcessingTimeMs,
                  overallConfidence: 0,
                  fieldConfidences: {},
                  finishReason: 'error',
                  error: errorMsg,
                },
              });
              await aiContextService.updateStatus(failedRecord.id, 'rejected');
            } catch (ctxErr: any) {
              console.warn(`[AudioContent-Regenerate] AiContext failed-record save failed (non-fatal): ${ctxErr.message}`);
            }

            failJob(job.jobId, getUserFriendlyError(new Error(errorMsg)));
          }
        } catch (sunoError: any) {
          console.error('[AudioContent] Regeneration Suno error:', sunoError.message);
          audioContent.providerStatus = 'failed';
          audioContent.status = 'failed';
          await audioContent.save();

          const regenProcessingTimeMs = Date.now() - regenStartTime;

          // Save failed Suno regeneration to AiContext for the AI Processing dashboard
          try {
            const failedRecord = await aiContextService.create({
              companyId,
              moduleSource: 'audio-content',
              analysisType: 'audio-content-regenerate',
              inputs: { songTitle: existing.songTitle } as any,
              analysis: {} as any,
              metadata: {
                pipelineVersion: '2.0',
                provider: 'suno',
                model: 'suno',
                tokensUsed: 0,
                processingTimeMs: regenProcessingTimeMs,
                overallConfidence: 0,
                fieldConfidences: {},
                finishReason: 'error',
                error: sunoError.message || 'Suno API error during regeneration',
              },
            });
            await aiContextService.updateStatus(failedRecord.id, 'rejected');
          } catch (ctxErr: any) {
            console.warn(`[AudioContent-Regenerate] AiContext failed-record save failed (non-fatal): ${ctxErr.message}`);
          }

          failJob(job.jobId, getUserFriendlyError(sunoError));
        }
      });

      return;
    }

    // Fallback: no audioContentId provided, use form data
    res.status(400).json({ error: 'Audio content ID is required for regeneration' });
  } catch (error: any) {
    console.error('Error starting song regeneration:', error);
    res.status(500).json({ error: 'Failed to start song regeneration', details: error.message });
  }
});

// ============================================
// GET /status/:jobId — Check AI job status
// ============================================

router.get('/status/:jobId', async (req: Request, res: Response) => {
  try {
    const { jobId } = req.params;
    const job = getJob(jobId);

    if (!job) {
      res.status(404).json({ error: 'Job not found' });
      return;
    }

    res.json({
      jobId: job.jobId,
      status: job.status,
      progress: job.progress,
      step: job.step,
      result: job.result?.autoFillData || null,
      error: job.error || null,
    });
  } catch (error: any) {
    console.error('Error fetching audio content job status:', error);
    res.status(500).json({ error: 'Failed to fetch job status', details: error.message });
  }
});

export default router;