/**
 * Testimonials AI Context Routes
 *
 * API endpoints for Testimonial AI generation.
 * POST /auto-fill — generate multiple testimonials from company context
 * POST /regenerate — regenerate testimonial data using existing context
 */

import express, { Request, Response } from 'express';
import { body, validationResult } from 'express-validator';
import { authenticate } from '../middleware/auth';
import { requirePermission } from '../middleware/permissions';
import { TestimonialPipeline } from '../services/aiContext/testimonialPipeline';
import { TestimonialPipelineInputs } from '../services/aiContext/testimonialPrompts';
import { aiContextService, computeTestimonialAutoFillMapping } 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('testimonials', '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, targetCount, customInstructions } = req.body;
    const count = Math.min(Math.max(Number(targetCount) || 5, 1), 8);
    const language = req.body.language || 'English';

    try {
      const job = createJob('testimonials', companyId, req.body._moduleId);

      // Return jobId immediately so the frontend can poll
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      // Run pipeline in background (do NOT await on the response path)
      setImmediate(async () => {
        try {
          const { Company, BusinessProfile, ICP } = 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 {}

          // Load brand strategy context for enrichment
          let brandStrategyData: any = null;
          try {
            const { ModuleData } = getModels();
            const brandStrategyDoc = await ModuleData.findOne({ moduleId: 'brand-strategy', companyId });
            if (brandStrategyDoc?.data) {
              brandStrategyData = brandStrategyDoc.data;
            }
          } catch {}

          // Build pipeline inputs
          const pipelineInputs: TestimonialPipelineInputs = {
            // 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,
            language,
          };

          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.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;
          }

          updateJobProgress(job.jobId, 10, 'Preparing context...');
          try {
            const pipeline = new TestimonialPipeline(pipelineInputs, (progress, step) => { updateJobProgress(job.jobId, progress, step); });
            const result = await pipeline.run();

            // Map each testimonial through the auto-fill mapping function
            const autoFillDataArray = result.testimonials.map((tAnalysis: Record<string, any>) =>
              computeTestimonialAutoFillMapping(tAnalysis)
            ).filter((data: Record<string, any>) => data.customerName);

            console.log(`[Testimonial-AutoFill] Generated ${autoFillDataArray.length} testimonials`);

            const combinedAnalysis: Record<string, any> = {
              testimonials: result.testimonials,
              pipelineVersion: result.pipelineVersion,
              provider: result.provider,
              aiModel: result.aiModel,
              tokensUsed: result.tokensUsed,
              inputTokens: result.inputTokens,
              outputTokens: result.outputTokens,
              processingTimeMs: result.processingTimeMs,
              overallConfidence: result.overallConfidence,
              latencyMs: result.latencyMs,
            };

            const context = await aiContextService.create({
              companyId,
              moduleSource: 'testimonials',
              analysisType: 'full-analysis',
              inputs: { companyName: company.name, description: pipelineInputs.companyDescription } as any,
              analysis: combinedAnalysis,
              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: result.fieldConfidences,
                finishReason: result.finishReason,
                apiKeyMasked: result.apiKeyMasked,
              },
            });

            await aiContextService.updateStatus(context.id, 'approved');

            completeJob(job.jobId, { testimonials: autoFillDataArray }, 'generated');
            console.log(`[Testimonial-AutoFill] Job ${job.jobId} completed. Generated ${autoFillDataArray.length} testimonials`);
          } catch (aiError: any) {
            console.error('[Testimonial-AutoFill] AI pipeline failed:', aiError.message);
            failJob(job.jobId, aiError.message || 'AI generation failed');
          }
        } catch (err: any) {
          console.error(`[Testimonial-AutoFill] Job ${job.jobId} failed:`, err.message);
          failJob(job.jobId, err.message || 'AI generation failed');
        }
      });
    } catch (error: any) {
      console.error('[Testimonial-AutoFill] Error:', error.message);
      res.status(500).json({ error: 'Failed to generate testimonial data', details: error.message });
    }
  }
);

// ============================================
// POST /regenerate
// ============================================

router.post(
  '/regenerate',
  requirePermission('testimonials', '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, existingTestimonialData } = req.body;
    const language = req.body.language || 'English';

    // Create job and return immediately
    const job = createJob('testimonials', companyId, req.body._moduleId);
    res.status(202).json({ jobId: job.jobId, status: 'processing' });

    // Run pipeline in background
    setImmediate(async () => {
      try {
        const { Company, BusinessProfile, ICP } = 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 {}

        // Load brand strategy context for enrichment
        let brandStrategyData: any = null;
        try {
          const { ModuleData } = getModels();
          const brandStrategyDoc = await ModuleData.findOne({ moduleId: 'brand-strategy', companyId });
          if (brandStrategyDoc?.data) {
            brandStrategyData = brandStrategyDoc.data;
          }
        } catch {}

        // Build pipeline inputs with existing testimonial data for regeneration
        const pipelineInputs: TestimonialPipelineInputs = {
          companyName: company.name,
          companyDescription: company.description || businessProfile?.description || undefined,
          companyIndustry: businessProfile?.primaryIndustry || undefined,
          companyBusinessModel: businessProfile?.businessModel || undefined,
          companyTargetAudience: undefined,
          companyPrimaryOffering: undefined,
          companyUsps: undefined,
          targetCount: 1, // Regenerate single testimonial
          language,
          // Existing testimonial identity for regeneration
          existingCustomerName: existingTestimonialData?.customerName || undefined,
          existingType: existingTestimonialData?.type || undefined,
          existingHeadline: existingTestimonialData?.headline || 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.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;
        }

        updateJobProgress(job.jobId, 10, 'Preparing context...');
        const pipeline = new TestimonialPipeline(pipelineInputs, (progress, step) => { updateJobProgress(job.jobId, progress, step); });
        const result = await pipeline.run();

        const autoFillDataArray = result.testimonials.map((tAnalysis: Record<string, any>) =>
          computeTestimonialAutoFillMapping(tAnalysis)
        ).filter((data: Record<string, any>) => data.customerName);

        const combinedAnalysis: Record<string, any> = {
          testimonials: result.testimonials,
          pipelineVersion: result.pipelineVersion,
          provider: result.provider,
          aiModel: result.aiModel,
          tokensUsed: result.tokensUsed,
          inputTokens: result.inputTokens,
          outputTokens: result.outputTokens,
          processingTimeMs: result.processingTimeMs,
          overallConfidence: result.overallConfidence,
          latencyMs: result.latencyMs,
        };

        const context = await aiContextService.create({
          companyId,
          moduleSource: 'testimonials',
          analysisType: 'full-analysis',
          inputs: { companyName: company.name, description: pipelineInputs.companyDescription } as any,
          analysis: combinedAnalysis,
          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: result.fieldConfidences,
            finishReason: result.finishReason,
            apiKeyMasked: result.apiKeyMasked,
          },
        });

        await aiContextService.updateStatus(context.id, 'approved');

        completeJob(job.jobId, { testimonials: autoFillDataArray }, 'regenerated');
        console.log(`[Testimonial-Regenerate] Job ${job.jobId} completed. Regenerated ${autoFillDataArray.length} testimonials`);
      } catch (err: any) {
        console.error(`[Testimonial-Regenerate] Job ${job.jobId} failed:`, err.message);
        failJob(job.jobId, err.message || 'AI regeneration failed');
      }
    });
  }
);

export default router;