/**
 * Video Content AI Context Routes
 *
 * API endpoints for Video Content AI generation.
 * POST /auto-fill — generate multiple video content pieces from company context
 * POST /regenerate — regenerate a single video content piece
 */

import express, { Request, Response } from 'express';
import { body, validationResult } from 'express-validator';
import { authenticate } from '../middleware/auth';
import { requirePermission } from '../middleware/permissions';
import { VideoContentPipeline } from '../services/aiContext/videoContentPipeline';
import { VideoContentPipelineInputs } from '../services/aiContext/videoContentPrompts';
import { aiContextService, computeVideoContentAutoFillMapping } from '../services/aiContext/aiContextService';
import { getModels } from '../models';
import { createJob, updateJobProgress, completeJob, failJob, getJob } from '../services/aiContext/aiJobManager';

const router = express.Router();
router.use(authenticate);

router.get(
  '/status/:jobId',
  async (req: Request, res: Response) => {
    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,
      error: job.error,
    });
  }
);

// ============================================
// POST /auto-fill
// ============================================

router.post(
  '/auto-fill',
  requirePermission('video-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;
    }

    const { companyId, topic, url, customInstructions } = req.body;
    const count = 1;

    try {
      const job = createJob('video-content', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          const { Company, BusinessProfile, ICP, Product } = getModels();
          const company = await Company.findById(companyId);
          if (!company) {
            failJob(job.jobId, 'Company not found');
            return;
          }

          let businessProfile: any = null;
          try { businessProfile = await BusinessProfile.findOne({ companyId }); } catch {}

          const companyContexts = await aiContextService.getByCompany(companyId, 'company-creation');
          const latestCompanyContext = companyContexts.find((c: any) => {
            const a = c.analysis?.toObject?.() || c.analysis || {};
            return c.status === 'approved' || a.industryType || a.businessModel || a.businessSummary;
          });

          let icpData: any = null;
          try { icpData = await ICP.findOne({ companyId, isActive: true }).sort({ createdAt: -1 }); } catch {}

          let brandStrategyData: any = null;
          try {
            const { ModuleData } = getModels();
            const brandStrategyDoc = await ModuleData.findOne({ moduleId: 'brand-strategy', companyId });
            if (brandStrategyDoc?.data) {
              brandStrategyData = brandStrategyDoc.data;
            }
          } catch {}

          let productNames: string[] | undefined;
          let productDescriptions: string[] | undefined;
          try {
            const products = await Product.find({ companyId }).limit(10);
            if (products.length > 0) {
              productNames = products.map((p: any) => p.name);
              productDescriptions = products.map((p: any) => p.description || p.shortDescription || '');
            }
          } catch {}

          const pipelineInputs: VideoContentPipelineInputs = {
            // The user's own brief from the "Generate with AI" popup or the AI Chat
            // generation flow. Stated as the highest-priority instruction in the
            // prompt, so it wins over the derived company context.
            customInstructions:
              typeof customInstructions === 'string' && customInstructions.trim()
                ? customInstructions.trim()
                : undefined,
            companyName: company.name,
            companyDescription: company.description || businessProfile?.description || undefined,
            companyIndustry: businessProfile?.primaryIndustry || undefined,
            companyBusinessModel: businessProfile?.businessModel || undefined,
            companyTargetAudience: undefined,
            companyPrimaryOffering: undefined,
            companyUsps: undefined,
            targetCount: count,
            topic: topic || undefined,
            url: url || undefined,
          };

          if (latestCompanyContext) {
            const analysis = (latestCompanyContext as any).analysis?.toObject?.() || (latestCompanyContext as any).analysis || {};
            if (analysis.industryType && !pipelineInputs.companyIndustry) pipelineInputs.companyIndustry = analysis.industryType;
            if (analysis.businessModel && !pipelineInputs.companyBusinessModel) pipelineInputs.companyBusinessModel = analysis.businessModel;
            if (analysis.targetAudience?.primary) pipelineInputs.companyTargetAudience = analysis.targetAudience.primary;
            if (analysis.primaryOffering) pipelineInputs.companyPrimaryOffering = analysis.primaryOffering;
            if (analysis.uspSuggestions?.length) pipelineInputs.companyUsps = analysis.uspSuggestions;
          }

          if (icpData) {
            pipelineInputs.icpName = icpData.name || undefined;
            pipelineInputs.icpIndustry = icpData.industry || undefined;
            pipelineInputs.icpCompanySize = icpData.companySize || undefined;
            pipelineInputs.icpPainPoints = icpData.painPoints || undefined;
            pipelineInputs.icpBusinessGoals = icpData.businessGoals || undefined;
          }

          if (brandStrategyData) {
            pipelineInputs.brandArchetype = brandStrategyData.brandArchetype || undefined;
            pipelineInputs.brandPersonality = brandStrategyData.brandPersonality || undefined;
            pipelineInputs.brandValues = brandStrategyData.brandValues || undefined;
            pipelineInputs.brandPositioning = brandStrategyData.brandPositioning || undefined;
            pipelineInputs.brandVoice = brandStrategyData.brandVoice || undefined;
          }

          if (productNames?.length) {
            pipelineInputs.productNames = productNames;
            pipelineInputs.productDescriptions = productDescriptions;
          }

          updateJobProgress(job.jobId, 10, 'Preparing context...');
          const pipeline = new VideoContentPipeline(pipelineInputs, (progress, step) => updateJobProgress(job.jobId, progress, step));
          const result = await pipeline.run();

          // Store full analysis in AiContext
          try {
            const context = await aiContextService.create({
              companyId,
              moduleSource: 'video-content',
              analysisType: 'full-analysis',
              inputs: { companyName: company.name, description: pipelineInputs.companyDescription, businessNotes: [pipelineInputs.topic, pipelineInputs.url].filter(Boolean).join(' | ') } as any,
              analysis: { videos: result.videos },
              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: result.overallConfidence,
                fieldConfidences: {},
                finishReason: result.finishReason,
                apiKeyMasked: result.apiKeyMasked,
              },
            });
            await aiContextService.updateStatus(context.id, 'approved');
          } catch (ctxErr: any) {
            console.warn(`[VideoContent-AutoFill] AiContext save failed (non-fatal): ${ctxErr.message}`);
          }

          // Map each video piece through the auto-fill mapping
          const autoFillDataArray = result.videos
            .map((vAnalysis) => computeVideoContentAutoFillMapping(vAnalysis))
            .filter((data) => data.name);

          completeJob(job.jobId, { videos: autoFillDataArray }, 'generated');
          console.log(`[VideoContent-AutoFill] Job ${job.jobId} completed. ${autoFillDataArray.length} video content pieces generated.`);
        } catch (err: any) {
          console.error(`[VideoContent-AutoFill] Job ${job.jobId} failed:`, err.message);
          failJob(job.jobId, err.message || 'AI generation failed');
        }
      });
    } catch (error: any) {
      console.error('[VideoContent-AutoFill] Error:', error.message);
      res.status(500).json({ error: 'Failed to generate video content', details: error.message });
    }
  }
);

// ============================================
// POST /regenerate (single piece)
// ============================================

router.post(
  '/regenerate',
  requirePermission('video-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;
    }

    const { companyId, topic, url } = req.body;

    const job = createJob('video-content', companyId, req.body._moduleId);
    res.status(202).json({ jobId: job.jobId, status: 'processing' });

    setImmediate(async () => {
      try {
        const { Company, BusinessProfile, ICP, Product } = getModels();
        const company = await Company.findById(companyId);
        if (!company) {
          failJob(job.jobId, 'Company not found');
          return;
        }

        let businessProfile: any = null;
        try { businessProfile = await BusinessProfile.findOne({ companyId }); } catch {}

        const companyContexts = await aiContextService.getByCompany(companyId, 'company-creation');
        const latestCompanyContext = companyContexts.find((c: any) => {
          const a = c.analysis?.toObject?.() || c.analysis || {};
          return c.status === 'approved' || a.industryType || a.businessModel || a.businessSummary;
        });

        let icpData: any = null;
        try { icpData = await ICP.findOne({ companyId, isActive: true }).sort({ createdAt: -1 }); } catch {}

        let brandStrategyData: any = null;
        try {
          const { ModuleData } = getModels();
          const brandStrategyDoc = await ModuleData.findOne({ moduleId: 'brand-strategy', companyId });
          if (brandStrategyDoc?.data) {
            brandStrategyData = brandStrategyDoc.data;
          }
        } catch {}

        let productNames: string[] | undefined;
        let productDescriptions: string[] | undefined;
        try {
          const products = await Product.find({ companyId }).limit(10);
          if (products.length > 0) {
            productNames = products.map((p: any) => p.name);
            productDescriptions = products.map((p: any) => p.description || p.shortDescription || '');
          }
        } catch {}

        const pipelineInputs: VideoContentPipelineInputs = {
          companyName: company.name,
          companyDescription: company.description || businessProfile?.description || undefined,
          companyIndustry: businessProfile?.primaryIndustry || undefined,
          companyBusinessModel: businessProfile?.businessModel || undefined,
          targetCount: 1,
          topic: topic || undefined,
          url: url || undefined,
        };

        if (latestCompanyContext) {
          const analysis = (latestCompanyContext as any).analysis?.toObject?.() || (latestCompanyContext as any).analysis || {};
          if (analysis.industryType && !pipelineInputs.companyIndustry) pipelineInputs.companyIndustry = analysis.industryType;
          if (analysis.businessModel && !pipelineInputs.companyBusinessModel) pipelineInputs.companyBusinessModel = analysis.businessModel;
          if (analysis.targetAudience?.primary) pipelineInputs.companyTargetAudience = analysis.targetAudience.primary;
          if (analysis.primaryOffering) pipelineInputs.companyPrimaryOffering = analysis.primaryOffering;
          if (analysis.uspSuggestions?.length) pipelineInputs.companyUsps = analysis.uspSuggestions;
        }

        if (icpData) {
          pipelineInputs.icpName = icpData.name || undefined;
          pipelineInputs.icpIndustry = icpData.industry || undefined;
          pipelineInputs.icpCompanySize = icpData.companySize || undefined;
          pipelineInputs.icpPainPoints = icpData.painPoints || undefined;
          pipelineInputs.icpBusinessGoals = icpData.businessGoals || undefined;
        }

        if (brandStrategyData) {
          pipelineInputs.brandArchetype = brandStrategyData.brandArchetype || undefined;
          pipelineInputs.brandPersonality = brandStrategyData.brandPersonality || undefined;
          pipelineInputs.brandValues = brandStrategyData.brandValues || undefined;
          pipelineInputs.brandPositioning = brandStrategyData.brandPositioning || undefined;
          pipelineInputs.brandVoice = brandStrategyData.brandVoice || undefined;
        }

        if (productNames?.length) {
          pipelineInputs.productNames = productNames;
          pipelineInputs.productDescriptions = productDescriptions;
        }

        updateJobProgress(job.jobId, 10, 'Preparing context...');
        const pipeline = new VideoContentPipeline(pipelineInputs, (progress, step) => updateJobProgress(job.jobId, progress, step));
        const result = await pipeline.run();

        const autoFillDataArray = result.videos
          .map((vAnalysis) => computeVideoContentAutoFillMapping(vAnalysis))
          .filter((data) => data.name);

        completeJob(job.jobId, { videos: autoFillDataArray }, 'regenerated');
        console.log(`[VideoContent-Regenerate] Job ${job.jobId} completed.`);
      } catch (err: any) {
        console.error(`[VideoContent-Regenerate] Job ${job.jobId} failed:`, err.message);
        failJob(job.jobId, err.message || 'AI regeneration failed');
      }
    });
  }
);

// ============================================
// POST /generate-video-prompt
// Generate an optimized video generation prompt from reviewed content
// ============================================

router.post(
  '/generate-video-prompt',
  requirePermission('video-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, reviewedContent } = req.body;
      const { Company } = getModels();
      const company = await Company.findById(companyId);

      // Build the video prompt from reviewed content
      const { buildVideoGenerationPrompt } = await import('../services/aiContext/videoContentPrompts');

      const promptInput = {
        description: reviewedContent?.description || '',
        script: reviewedContent?.script || '',
        summary: reviewedContent?.summary || '',
        keyNotes: reviewedContent?.keyNotes || [],
        tags: reviewedContent?.tags || [],
        language: reviewedContent?.language || 'en',
        department: reviewedContent?.department || '',
        targetAudience: reviewedContent?.targetAudience || '',
        videoType: reviewedContent?.type || '',
        companyName: company?.name || '',
      };

      let videoPrompt = buildVideoGenerationPrompt(promptInput);

      // Optionally enhance the prompt with AI
      try {
        const { generateWithAI } = await import('../utils/aiProvider');
        const enhanceResult = await generateWithAI(
          `You are an expert at creating prompts for AI video generation tools like Luma AI. Transform the following description into an optimized, cinematic video generation prompt. The prompt should be visual, descriptive, and suitable for direct input into an AI video generator. Focus on visual scenes, camera angles, lighting, mood, and transitions. Keep it concise but detailed.\n\nOriginal description: ${videoPrompt}`,
          'Create an optimized video generation prompt. Focus on visual storytelling, cinematography, and scene composition. The output should be a single paragraph prompt ready for AI video generation.',
          1000,
          0.7,
          'text',
          'auto',
          undefined,
          req.user?._id?.toString()
        );

        if (enhanceResult?.content && enhanceResult.content.trim()) {
          videoPrompt = enhanceResult.content.trim();
        }
      } catch (aiErr: any) {
        console.warn('[VideoContent] AI prompt enhancement failed, using base prompt:', aiErr.message);
        // Fall back to the base prompt — this is non-fatal
      }

      res.json({ prompt: videoPrompt });
    } catch (error: any) {
      console.error('[VideoContent] Generate video prompt error:', error.message);
      res.status(500).json({ error: 'Failed to generate video prompt', details: error.message });
    }
  }
);

// ============================================
// POST /generate-video
// Generate a video using the selected provider (Luma AI)
// ============================================

router.post(
  '/generate-video',
  requirePermission('video-content', 'ai-generate'),
  [
    body('companyId').notEmpty().withMessage('Company ID is required'),
    body('prompt').notEmpty().withMessage('Video 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;
    }

    const { companyId, prompt, model, metadata } = req.body;

    try {
      // Determine the video provider from the model
      const { getImageProviderForModel } = await import('../utils/aiProvider');
      const provider = model ? getImageProviderForModel(model) : 'luma';

      if (provider !== 'luma') {
        res.status(400).json({ error: `Video generation with provider '${provider}' is not yet supported. Only Luma AI is currently available.` });
        return;
      }

      // Check that Luma AI key is configured
      const { providerHasActiveKey, getAIConfig } = await import('../utils/aiProvider');
      const config = await getAIConfig(req.user?._id?.toString());
      if (!providerHasActiveKey('luma', config)) {
        const stats = await import('../utils/aiProvider').then(m => m.getConfiguredKeyStats(config._dbConfig, 'luma'));
        if (stats.total > 0 && stats.inactive === stats.total) {
          res.status(400).json({ error: 'All Luma AI API keys are currently inactive. Please check your Super Admin settings and activate at least one key.' });
          return;
        }
        res.status(400).json({ error: 'No Luma AI API key configured. Add one in Super Admin > AI Configuration > Luma AI.' });
        return;
      }

      // Create a job for tracking progress
      const job = createJob('video-content', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      // Run video generation asynchronously
      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Starting video generation...');

          const { generateVideoWithLuma } = await import('../services/aiContext/lumaVideoGeneration');
          const result = await generateVideoWithLuma(prompt, {
            model: model || 'ray-2',
            userId: req.user?._id?.toString(),
          });

          updateJobProgress(job.jobId, 80, 'Video generated, saving record...');

          // Create the video content record
          const { VideoContent } = getModels();
          const videoData: any = {
            companyId,
            name: metadata?.name || 'AI Generated Video',
            description: metadata?.description || '',
            type: metadata?.type || 'educational',
            category: metadata?.category || 'educational',
            source: 'internal-cdn',
            videoUrl: result.videoUrl,
            thumbnailUrl: result.thumbnailUrl || '',
            summary: metadata?.summary || '',
            script: metadata?.script || '',
            keyNotes: metadata?.keyNotes || [],
            tags: metadata?.tags || [],
            language: metadata?.language || 'en',
            department: metadata?.department || '',
            targetAudience: metadata?.targetAudience || '',
            status: 'draft',
            accessLevel: 'team',
            aiGenerated: true,
            aiGenerationContext: {
              pipelineVersion: '2.0',
              provider: 'luma',
              model: result.model,
              videoPrompt: prompt,
              videoGenerationId: result.generationId,
              generatedAt: new Date().toISOString(),
            },
            ...(metadata?.duration ? { duration: metadata.duration } : {}),
          };

          const savedVideo = await VideoContent.create(videoData);

          completeJob(job.jobId, {
            videoId: savedVideo._id?.toString() || savedVideo.id,
            videoUrl: result.videoUrl,
            thumbnailUrl: result.thumbnailUrl,
            model: result.model,
            provider: result.provider,
            generationId: result.generationId,
            latencyMs: result.latencyMs,
          }, 'generated');

          console.log(`[VideoContent-GenerateVideo] Job ${job.jobId} completed. Video ${savedVideo._id} created.`);
        } catch (err: any) {
          console.error(`[VideoContent-GenerateVideo] Job ${job.jobId} failed:`, err.message);
          failJob(job.jobId, err.message || 'Video generation failed');
        }
      });
    } catch (error: any) {
      console.error('[VideoContent-GenerateVideo] Error:', error.message);
      res.status(500).json({ error: 'Failed to start video generation', details: error.message });
    }
  }
);

export default router;