/**
 * PR Content Engine AI Context Routes
 *
 * API endpoints for PR AI content generation:
 * POST /generate-expert-columns  — Generate 52-week expert column plan
 * POST /generate-expert-column   — Generate a single expert column article
 * POST /generate-press-release   — Generate a press release
 * POST /generate-bio             — Generate a founder/executive bio
 * POST /generate-media-kit       — Generate a media kit
 */

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 { aiContextService } from '../services/aiContext/aiContextService';
import { createJob, updateJobProgress, completeJob, failJob, getJob } from '../services/aiContext/aiJobManager';
import {
  ExpertColumnPlanPipeline,
  ExpertColumnPipeline,
  ExpertColumnPlanWithContentPipeline,
  PressReleasePipeline,
  BioPipeline,
  MediaKitPipeline,
  NewsStoryPipeline,
  ThoughtLeadershipPipeline,
  HeadlinePipeline,
  QuotePipeline,
  MediaOutreachPipeline,
  CalendarSuggestionPipeline,
  RepurposePipeline,
  WikipediaArticlePipeline,
  WikipediaNotabilityPipeline,
  WikipediaCitationPipeline,
  KnowledgePanelPipeline,
  KnowledgePanelOptimisationPipeline,
  KnowledgePanelSchemaPipeline,
  KPSummaryPipeline,
  KPSectionContentPipeline,
  KPInsightsPipeline,
  KPFAQsPipeline,
} from '../services/aiContext/prPipeline';
import { PRContentInputs } from '../services/aiContext/prPrompts';

const router = express.Router();
router.use(authenticate);

// Helper: Save AI generation record with token metadata
async function saveAiGenerationRecord(params: {
  companyId: string;
  moduleSource: string;
  analysisType: string;
  inputs: Record<string, any>;
  analysis: Record<string, any>;
  metadata: {
    provider: string;
    model: string;
    tokensUsed: number;
    inputTokens: number;
    outputTokens: number;
    processingTimeMs: number;
  };
}): Promise<void> {
  try {
    await aiContextService.create({
      companyId: params.companyId,
      moduleSource: params.moduleSource,
      analysisType: params.analysisType,
      inputs: params.inputs as any,
      analysis: params.analysis,
      metadata: {
        pipelineVersion: '1.0.0',
        provider: params.metadata.provider,
        model: params.metadata.model,
        tokensUsed: params.metadata.tokensUsed,
        inputTokens: params.metadata.inputTokens,
        outputTokens: params.metadata.outputTokens,
        processingTimeMs: params.metadata.processingTimeMs,
        latencyMs: params.metadata.processingTimeMs,
        overallConfidence: 85,
        fieldConfidences: {},
        finishReason: 'stop',
      },
    });
  } catch (error: any) {
    console.error('[PR AI] Failed to save AI generation record:', error.message);
  }
}

// Helper: gather company context for PR content generation
async function buildPRContentInputs(companyId: string, overrides: Partial<PRContentInputs> = {}): Promise<PRContentInputs> {
  const { Company, BusinessProfile, ICP, Product, Founder, Brand, Competitor } = getModels();

  const company = await Company.findById(companyId);
  const businessProfile = await BusinessProfile.findOne({ companyId });
  const icps = await ICP.find({ companyId }).limit(1);
  const products = await Product.find({ companyId }).limit(5);
  const founders = await Founder.find({ companyId }).limit(1);
  const brand = await Brand.findOne({ companyId });
  const competitors = await Competitor.find({ companyId }).limit(5);

  const inputs: PRContentInputs = {
    companyName: company?.name || 'Unknown Company',
    companyDescription: businessProfile?.description || businessProfile?.mission || undefined,
    companyIndustry: businessProfile?.industry || undefined,
    companyBusinessModel: businessProfile?.businessModel || undefined,
    companyTargetAudience: businessProfile?.targetAudience || undefined,
    companyPrimaryOffering: businessProfile?.primaryOffering || undefined,
    companyUsps: businessProfile?.usps || undefined,
    companyWebsite: businessProfile?.website || undefined,
    ...overrides,
  };

  // ICP context
  if (icps.length > 0) {
    const icp = icps[0] as any;
    inputs.icpName = icp.name;
    inputs.icpIndustry = icp.industry;
    inputs.icpPainPoints = icp.painPoints;
  }

  // Founder context
  if (founders.length > 0) {
    const founder = founders[0] as any;
    inputs.founderName = founder.name;
    inputs.founderTitle = founder.title || founder.role;
    inputs.founderBio = founder.bio || founder.description;
    inputs.founderAchievements = founder.achievements || founder.keyAchievements;
  }

  // Brand context
  if (brand) {
    const b = brand as any;
    inputs.brandArchetype = b.archetype || b.brandArchetype;
    inputs.brandPersonality = b.personality || b.brandPersonality;
    inputs.brandVoice = b.voice || b.brandVoice;
  }

  // Product context
  if (products.length > 0) {
    inputs.productNames = products.map((p: any) => p.name);
    inputs.productDescriptions = products.map((p: any) => p.description || p.shortDescription);
  }

  // Competitor context (for Wikipedia notability and Knowledge Panel)
  if (competitors.length > 0) {
    inputs.competitorContext = competitors.map((c: any) =>
      `${c.name}${c.description ? ': ' + c.description : ''}${c.strengths ? ' | Strengths: ' + (Array.isArray(c.strengths) ? c.strengths.join(', ') : c.strengths) : ''}`
    ).join('\n');
  }

  return inputs;
}

// ============================================
// JOB STATUS
// ============================================

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,
    });
  }
);

// ============================================
// GENERATE EXPERT COLUMN PLAN WITH FULL CONTENT
// Generates plan + complete content for each article
// ============================================

router.post(
  '/generate-expert-columns',
  requirePermission('pr', '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, format, tone, tones, customTone, wordCount, numberOfWeeks, contentStrategy, topic, language } = req.body;

    // Generate a unique seed for this generation to ensure uniqueness
    const uniquenessSeed = `pr-plan-${Date.now()}-${Math.random().toString(36).substring(2, 15)}-${companyId}`;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          // Progress callback for reporting article generation progress
          const onProgress = (step: string, progress: number) => {
            updateJobProgress(job.jobId, progress, step);
          };

          updateJobProgress(job.jobId, 5, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, {
            format,
            tone,
            tones,
            customTone,
            wordCount,
            numberOfWeeks,
            uniquenessSeed,
            topic,
            contentStrategy,
            language,
          });

          updateJobProgress(job.jobId, 10, `Generating ${numberOfWeeks || 4}-week content plan`);

          // Use the enhanced pipeline that generates plan + full content for each article
          const result = await ExpertColumnPlanWithContentPipeline(inputs, onProgress, 'ollama', true);

          if (!result || !result.articles || result.articles.length === 0) {
            failJob(job.jobId, 'AI returned empty or no articles. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 95, 'Finalizing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };

          // Prepare the response data
          const autoFillData = {
            name: result.name,
            numberOfWeeks: result.numberOfWeeks,
            format: result.format,
            tone: result.tone,
            // Echo the requested tone selection so the saved plan keeps the full
            // multi-tone choice, not just the primary tone.
            ...(tones?.length ? { tones } : {}),
            ...(customTone ? { customTone } : {}),
            articles: result.articles,
            // Summary info
            summary: {
              totalArticles: result.articles.length,
              articlesWithContent: result.articles.filter((a: any) => a.article).length,
              articlesWithoutContent: result.articles.filter((a: any) => !a.article).length,
            },
          };

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'expert-column-plan-with-content',
            inputs: { format, tone, wordCount, numberOfWeeks, uniquenessSeed, contentStrategy, topic },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-expert-columns');
        } catch (error: any) {
          console.error('[PR AI] Expert column plan generation failed:', error);
          failJob(job.jobId, error.message || 'Expert column plan generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE SINGLE EXPERT COLUMN
// ============================================

router.post(
  '/generate-expert-column',
  requirePermission('pr', '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, format, tone, tones, customTone, wordCount, weekNumber, topic, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { format, tone, tones, customTone, wordCount, weekNumber, topic, language });

          updateJobProgress(job.jobId, 30, 'Generating expert column article');
          const result = await ExpertColumnPipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          // Echo the requested tone selection back with the result so the saved
          // record keeps the full multi-tone choice, not just the primary tone.
          if (tones?.length) autoFillData.tones = tones;
          if (customTone) autoFillData.customTone = customTone;
          delete autoFillData._metadata;

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'expert-column',
            inputs: { format, tone, wordCount, weekNumber, topic },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-expert-column');
        } catch (error: any) {
          console.error('[PR AI] Expert column generation failed:', error);
          failJob(job.jobId, error.message || 'Expert column generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE PRESS RELEASE
// ============================================

router.post(
  '/generate-press-release',
  requirePermission('pr', '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, title, eventType, keyAnnouncement, customNotes, wordCount, tone, tones, customTone, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { title, eventType, keyAnnouncement, customNotes, wordCount, tone, tones, customTone, language });

          updateJobProgress(job.jobId, 30, 'Generating press release');
          const result = await PressReleasePipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          // Echo the requested tone selection back with the result so the saved
          // record keeps the full multi-tone choice, not just the primary tone.
          if (tones?.length) autoFillData.tones = tones;
          if (customTone) autoFillData.customTone = customTone;
          delete autoFillData._metadata;

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'press-release',
            inputs: { title, eventType, keyAnnouncement, customNotes, wordCount },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-press-release');
        } catch (error: any) {
          console.error('[PR AI] Press release generation failed:', error);
          failJob(job.jobId, error.message || 'Press release generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE BIO
// ============================================

router.post(
  '/generate-bio',
  requirePermission('pr', '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, bioType, personName, tone, tones, customTone, wordCount, customNotes, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { bioType, personName, tone, tones, customTone, wordCount, customNotes, language });

          updateJobProgress(job.jobId, 30, 'Generating bio');
          const result = await BioPipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          // Echo the requested tone selection back with the result so the saved
          // record keeps the full multi-tone choice, not just the primary tone.
          if (tones?.length) autoFillData.tones = tones;
          if (customTone) autoFillData.customTone = customTone;
          delete autoFillData._metadata;

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'founder-bio',
            inputs: { bioType, personName, tone, wordCount, customNotes },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-bio');
        } catch (error: any) {
          console.error('[PR AI] Bio generation failed:', error);
          failJob(job.jobId, error.message || 'Bio generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE MEDIA KIT
// ============================================

router.post(
  '/generate-media-kit',
  requirePermission('pr', '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, customNotes, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { customNotes, language });

          updateJobProgress(job.jobId, 30, 'Generating media kit');
          const result = await MediaKitPipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'media-kit',
            inputs: { customNotes },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-media-kit');
        } catch (error: any) {
          console.error('[PR AI] Media kit generation failed:', error);
          failJob(job.jobId, error.message || 'Media kit generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE NEWS STORY
// ============================================

router.post(
  '/generate-news-story',
  requirePermission('pr', '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, eventType, keyAnnouncement, customNotes, wordCount, tone, tones, customTone, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { eventType, keyAnnouncement, customNotes, wordCount, tone, tones, customTone, language });

          updateJobProgress(job.jobId, 30, 'Generating news story');
          const result = await NewsStoryPipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          // Echo the requested tone selection back with the result so the saved
          // record keeps the full multi-tone choice, not just the primary tone.
          if (tones?.length) autoFillData.tones = tones;
          if (customTone) autoFillData.customTone = customTone;
          delete autoFillData._metadata;

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'news-story',
            inputs: { eventType, keyAnnouncement, customNotes, wordCount, tone },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-news-story');
        } catch (error: any) {
          console.error('[PR AI] News story generation failed:', error);
          failJob(job.jobId, error.message || 'News story generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE THOUGHT LEADERSHIP
// ============================================

router.post(
  '/generate-thought-leadership',
  requirePermission('pr', '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, contentType, topic, tone, tones, customTone, wordCount, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { contentType, topic, tone, tones, customTone, wordCount, language });

          updateJobProgress(job.jobId, 30, 'Generating thought leadership content');
          const result = await ThoughtLeadershipPipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          // Echo the requested tone selection back with the result so the saved
          // record keeps the full multi-tone choice, not just the primary tone.
          if (tones?.length) autoFillData.tones = tones;
          if (customTone) autoFillData.customTone = customTone;
          delete autoFillData._metadata;

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'thought-leadership',
            inputs: { contentType, topic, tone, wordCount },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-thought-leadership');
        } catch (error: any) {
          console.error('[PR AI] Thought leadership generation failed:', error);
          failJob(job.jobId, error.message || 'Thought leadership generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE HEADLINES
// ============================================

router.post(
  '/generate-headlines',
  requirePermission('pr', '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, contentTitle, contentSummary, contentType, categories, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { language });

          updateJobProgress(job.jobId, 30, 'Generating headline options');
          const result = await HeadlinePipeline({
            ...inputs,
            contentTitle,
            contentSummary,
            contentType,
            categories,
          }, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'headlines',
            inputs: { contentTitle, contentSummary, contentType, categories },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-headlines');
        } catch (error: any) {
          console.error('[PR AI] Headline generation failed:', error);
          failJob(job.jobId, error.message || 'Headline generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE QUOTES
// ============================================

router.post(
  '/generate-quotes',
  requirePermission('pr', '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, contentId, contentText, quoteType, tone, tones, customTone, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { language });

          updateJobProgress(job.jobId, 30, 'Generating quotes');
          const result = await QuotePipeline({
            ...inputs,
            contentId,
            contentText,
            quoteType,
            tone,
            tones,
            customTone,
          }, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          // Echo the requested tone selection back with the result so the saved
          // record keeps the full multi-tone choice, not just the primary tone.
          if (tones?.length) autoFillData.tones = tones;
          if (customTone) autoFillData.customTone = customTone;
          delete autoFillData._metadata;

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'quotes',
            inputs: { contentId, contentText, quoteType, tone },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-quotes');
        } catch (error: any) {
          console.error('[PR AI] Quote generation failed:', error);
          failJob(job.jobId, error.message || 'Quote generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE MEDIA OUTREACH
// ============================================

router.post(
  '/generate-media-outreach',
  requirePermission('pr', '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, outreachType, linkedContentId, linkedContentType, recipientName, recipientOrganization, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { language });

          updateJobProgress(job.jobId, 30, 'Generating media outreach');
          const result = await MediaOutreachPipeline({
            ...inputs,
            outreachType,
            linkedContentId,
            linkedContentType,
            recipientName,
            recipientOrganization,
          }, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'media-outreach',
            inputs: { outreachType, linkedContentId, linkedContentType, recipientName, recipientOrganization },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-media-outreach');
        } catch (error: any) {
          console.error('[PR AI] Media outreach generation failed:', error);
          failJob(job.jobId, error.message || 'Media outreach generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE CALENDAR SUGGESTIONS
// ============================================

router.post(
  '/generate-calendar-suggestions',
  requirePermission('pr', '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, frequency, focusAreas, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { language });

          updateJobProgress(job.jobId, 30, 'Generating calendar suggestions');
          const result = await CalendarSuggestionPipeline({
            ...inputs,
            frequency,
            focusAreas,
          }, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'calendar-suggestions',
            inputs: { frequency, focusAreas },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-calendar-suggestions');
        } catch (error: any) {
          console.error('[PR AI] Calendar suggestion generation failed:', error);
          failJob(job.jobId, error.message || 'Calendar suggestion generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// REPURPOSE CONTENT
// ============================================

router.post(
  '/repurpose-content',
  requirePermission('pr', '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, sourceId, sourceType, targetFormat, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { language });

          // Fetch source content for repurposing
          const models = getModels();
          let sourceContent = '';
          if (sourceType === 'press-release') {
            const item = await models.PressRelease.findById(sourceId);
            sourceContent = item ? `${(item as any).headline || ''}\n\n${(item as any).body || ''}` : '';
          } else if (sourceType === 'expert-column') {
            const item = await models.ExpertColumn.findById(sourceId);
            sourceContent = item ? `${(item as any).headline || ''}\n\n${(item as any).mainContent || ''}` : '';
          } else if (sourceType === 'news-story') {
            const item = await models.NewsStory.findById(sourceId);
            sourceContent = item ? `${(item as any).headline || ''}\n\n${(item as any).articleBody || ''}` : '';
          } else if (sourceType === 'thought-leadership') {
            const item = await models.ThoughtLeadership.findById(sourceId);
            sourceContent = item ? `${(item as any).headline || ''}\n\n${(item as any).mainContent || ''}` : '';
          }

          updateJobProgress(job.jobId, 30, 'Repurposing content');
          const result = await RepurposePipeline({
            ...inputs,
            sourceId,
            sourceType,
            sourceContent,
            targetFormat,
          }, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          // Extract metadata from result
          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          // Save AI generation record with token metadata
          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'repurpose-content',
            inputs: { sourceId, sourceType, targetFormat },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-repurpose');
        } catch (error: any) {
          console.error('[PR AI] Content repurposing failed:', error);
          failJob(job.jobId, error.message || 'Content repurposing failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE WIKIPEDIA ARTICLE
// ============================================

router.post(
  '/generate-wikipedia-article',
  requirePermission('pr', '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, wikiArticleTopic, wikiSectionNames, wikiExistingContent, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { wikiArticleTopic, wikiSectionNames, wikiExistingContent, language });

          updateJobProgress(job.jobId, 30, 'Generating Wikipedia article draft');
          const result = await WikipediaArticlePipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'wikipedia-article',
            inputs: { wikiArticleTopic, wikiSectionNames, wikiExistingContent },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-wikipedia-article');
        } catch (error: any) {
          console.error('[PR AI] Wikipedia article generation failed:', error);
          failJob(job.jobId, error.message || 'Wikipedia article generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE WIKIPEDIA NOTABILITY CHECK
// ============================================

router.post(
  '/generate-wikipedia-notability',
  requirePermission('pr', '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, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { language });

          updateJobProgress(job.jobId, 30, 'Assessing Wikipedia notability');
          const result = await WikipediaNotabilityPipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'wikipedia-notability',
            inputs: {},
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-wikipedia-notability');
        } catch (error: any) {
          console.error('[PR AI] Wikipedia notability check failed:', error);
          failJob(job.jobId, error.message || 'Wikipedia notability check failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE WIKIPEDIA CITATIONS
// ============================================

router.post(
  '/generate-wikipedia-citations',
  requirePermission('pr', '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, claims, articleContent, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { claims, articleContent, language });

          updateJobProgress(job.jobId, 30, 'Generating citation suggestions');
          const result = await WikipediaCitationPipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'wikipedia-citations',
            inputs: { claims, articleContent },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-wikipedia-citations');
        } catch (error: any) {
          console.error('[PR AI] Wikipedia citation generation failed:', error);
          failJob(job.jobId, error.message || 'Wikipedia citation generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE KNOWLEDGE PANEL DATA
// ============================================

router.post(
  '/generate-knowledge-panel',
  requirePermission('pr', '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, kpPanelType, kpCurrentData, kpDesiredFields, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { kpPanelType, kpCurrentData, kpDesiredFields, language });

          updateJobProgress(job.jobId, 30, 'Generating Knowledge Panel data');
          const result = await KnowledgePanelPipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'knowledge-panel',
            inputs: { kpPanelType, kpCurrentData, kpDesiredFields },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-knowledge-panel');
        } catch (error: any) {
          console.error('[PR AI] Knowledge Panel generation failed:', error);
          failJob(job.jobId, error.message || 'Knowledge Panel generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE KNOWLEDGE PANEL OPTIMISATIONS
// ============================================

router.post(
  '/generate-kp-optimisations',
  requirePermission('pr', '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, kpCurrentData, kpPanelType, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { kpCurrentData, kpPanelType, language });

          updateJobProgress(job.jobId, 30, 'Generating Knowledge Panel optimisations');
          const result = await KnowledgePanelOptimisationPipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'kp-optimisations',
            inputs: { kpCurrentData, kpPanelType },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-kp-optimisations');
        } catch (error: any) {
          console.error('[PR AI] Knowledge Panel optimisations failed:', error);
          failJob(job.jobId, error.message || 'Knowledge Panel optimisations failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// GENERATE KNOWLEDGE PANEL SCHEMA MARKUP
// ============================================

router.post(
  '/generate-kp-schema',
  requirePermission('pr', '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, kpPanelType, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { kpPanelType, language });

          updateJobProgress(job.jobId, 30, 'Generating Knowledge Panel schema markup');
          const result = await KnowledgePanelSchemaPipeline(inputs, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'kp-schema',
            inputs: { kpPanelType },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-kp-schema');
        } catch (error: any) {
          console.error('[PR AI] Knowledge Panel schema generation failed:', error);
          failJob(job.jobId, error.message || 'Knowledge Panel schema generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// KNOWLEDGE PANEL SUMMARY GENERATION
// ============================================

router.post(
  '/generate-kp-summary',
  requirePermission('pr', '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, kpTitle, kpCategory, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { language });

          updateJobProgress(job.jobId, 30, 'Generating Knowledge Panel summary');
          const result = await KPSummaryPipeline({ ...inputs, kpTitle, kpCategory }, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'kp-summary',
            inputs: { kpTitle, kpCategory },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-kp-summary');
        } catch (error: any) {
          console.error('[PR AI] KP summary generation failed:', error);
          failJob(job.jobId, error.message || 'KP summary generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// KNOWLEDGE PANEL SECTION CONTENT GENERATION
// ============================================

router.post(
  '/generate-kp-section-content',
  requirePermission('pr', '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, kpTitle, sectionType, sectionTitle, existingContent, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { language });

          updateJobProgress(job.jobId, 30, 'Generating section content');
          const result = await KPSectionContentPipeline({ ...inputs, kpTitle, sectionType, sectionTitle, existingContent }, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'kp-section-content',
            inputs: { kpTitle, sectionType, sectionTitle, existingContent },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-kp-section-content');
        } catch (error: any) {
          console.error('[PR AI] KP section content generation failed:', error);
          failJob(job.jobId, error.message || 'KP section content generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// KNOWLEDGE PANEL INSIGHTS GENERATION
// ============================================

router.post(
  '/generate-kp-insights',
  requirePermission('pr', '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, kpTitle, kpCategory, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { language });

          updateJobProgress(job.jobId, 30, 'Generating insights');
          const result = await KPInsightsPipeline({ ...inputs, kpTitle, kpCategory }, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'kp-insights',
            inputs: { kpTitle, kpCategory },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-kp-insights');
        } catch (error: any) {
          console.error('[PR AI] KP insights generation failed:', error);
          failJob(job.jobId, error.message || 'KP insights generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

// ============================================
// KNOWLEDGE PANEL FAQ GENERATION
// ============================================

router.post(
  '/generate-kp-faqs',
  requirePermission('pr', '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, kpTitle, kpCategory, language } = req.body;

    try {
      const job = createJob('pr', companyId, req.body._moduleId);
      res.status(202).json({ jobId: job.jobId, status: 'processing' });

      setImmediate(async () => {
        try {
          updateJobProgress(job.jobId, 10, 'Gathering company context');
          const inputs = await buildPRContentInputs(companyId, { language });

          updateJobProgress(job.jobId, 30, 'Generating FAQs');
          const result = await KPFAQsPipeline({ ...inputs, kpTitle, kpCategory }, 'ollama', true);
          if (!result || Object.keys(result).length === 0) {
            failJob(job.jobId, 'AI returned empty or unparseable response. Please try again.');
            return;
          }

          updateJobProgress(job.jobId, 80, 'Processing results');

          const metadata = result._metadata || { provider: 'unknown', model: 'unknown', tokensUsed: 0, inputTokens: 0, outputTokens: 0, processingTimeMs: 0 };
          const autoFillData = { ...result };
          delete autoFillData._metadata;

          await saveAiGenerationRecord({
            companyId,
            moduleSource: 'pr',
            analysisType: 'kp-faqs',
            inputs: { kpTitle, kpCategory },
            analysis: autoFillData,
            metadata: {
              provider: metadata.provider,
              model: metadata.model,
              tokensUsed: metadata.tokensUsed,
              inputTokens: metadata.inputTokens,
              outputTokens: metadata.outputTokens,
              processingTimeMs: metadata.processingTimeMs,
            },
          });

          completeJob(job.jobId, autoFillData, 'pr-kp-faqs');
        } catch (error: any) {
          console.error('[PR AI] KP FAQs generation failed:', error);
          failJob(job.jobId, error.message || 'KP FAQs generation failed');
        }
      });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

export default router;