/**
 * Presentation Routes
 *
 * CRUD operations, AI generation, version history, and export for presentations.
 */

import express, { Request, Response } from 'express';
import { body, validationResult } from 'express-validator';
import { getModels } from '../models';
import { requireRole } from '../middleware/auth';
import { authenticateJwtOrApiToken } from '../middleware/dualAuth';
import { requirePermission } from '../middleware/permissions';
import { buildLanguageInstruction } from '../services/aiContext/prPrompts';
import { createJob, completeJob, failJob } from '../services/aiContext/aiJobManager';

const router = express.Router();

router.use(authenticateJwtOrApiToken);

// ============================================
// CRUD ROUTES
// ============================================

// Get all presentations for a company
router.get('/:companyId', async (req: Request, res: Response) => {
  try {
    const { companyId } = req.params;
    const { type, status } = req.query;
    const { Presentation } = getModels();

    if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    const filter: Record<string, unknown> = { companyId };
    if (type) filter.type = type;
    if (status) filter.status = status;

    const presentations = await Presentation.find(filter).sort({ createdAt: -1 });
    res.json(presentations);
  } catch (error) {
    console.error('[Presentations GET Error]', error);
    res.status(500).json({ error: 'Failed to get presentations' });
  }
});

// Get single presentation
router.get('/detail/:id', async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { Presentation } = getModels();

    const presentation = await Presentation.findById(id);
    if (!presentation) {
      res.status(404).json({ error: 'Presentation not found' });
      return;
    }

    if (!req.user!.companyIds.includes(presentation.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    res.json(presentation);
  } catch (error) {
    console.error('[Presentation GET Error]', error);
    res.status(500).json({ error: 'Failed to get presentation' });
  }
});

// Create presentation
router.post(
  '/',
  requirePermission('presentations', 'create'),
  [
    body('title').trim().notEmpty().withMessage('Title is required'),
    body('companyId').notEmpty().withMessage('Company ID is required'),
    body('type').isIn([
      'company-profile',
      'product',
      'investor-pitch',
      'event-outdoor',
      'sales-pitch',
      'marketing-campaign',
      'training-onboarding',
      'quarterly-review',
      'project-proposal',
      'partnership-proposal',
      'investor-update',
      'product-launch',
      'case-study',
    ]).withMessage('Invalid type'),
    body('businessName').trim().notEmpty().withMessage('Business name is required'),
    body('industry').trim().notEmpty().withMessage('Industry is required'),
    body('targetAudience').trim().notEmpty().withMessage('Target audience is required'),
    body('keyMessage').trim().notEmpty().withMessage('Key message is required'),
  ],
  async (req: Request, res: Response) => {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        res.status(400).json({ errors: errors.array() });
        return;
      }

      if (!req.user!.companyIds.includes(req.body.companyId) && req.user!.role !== 'admin') {
        res.status(403).json({ error: 'Access denied' });
        return;
      }

      const { Presentation } = getModels();
      const cleanBody = Object.fromEntries(
        Object.entries(req.body).filter(([, v]) => v !== '')
      );
      const presentation = new Presentation({ ...cleanBody, createdBy: req.user!._id });
      await presentation.save();

      res.status(201).json(presentation);
    } catch (error: unknown) {
      const err = error as Error & { name?: string; errors?: Record<string, { message: string }> };
      console.error('[Presentation Create Error]', err?.message || err);
      if (err?.name === 'ValidationError') {
        const messages = Object.values(err.errors || {}).map((e: { message: string }) => e.message);
        res.status(400).json({ error: messages.join('. '), details: err?.message });
        return;
      }
      res.status(500).json({ error: 'Failed to create presentation', details: err?.message });
    }
  }
);

// Update presentation
router.put('/:id', requirePermission('presentations', 'edit'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { Presentation } = getModels();

    const presentation = await Presentation.findById(id);
    if (!presentation) {
      res.status(404).json({ error: 'Presentation not found' });
      return;
    }

    if (!req.user!.companyIds.includes(presentation.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    // Save current version to previousVersions before update
    if (req.body.slides && !req.body.skipVersioning) {
      const currentVersion = {
        version: presentation.version,
        slides: presentation.slides,
        savedAt: new Date(),
        savedBy: req.user!._id,
      };

      presentation.previousVersions = presentation.previousVersions || [];
      presentation.previousVersions.push(currentVersion);
      presentation.version = (presentation.version || 1) + 1;
    }

    const cleanBody = Object.fromEntries(
      Object.entries(req.body).filter(([, v]) => v !== '')
    );
    Object.assign(presentation, cleanBody, { updatedAt: new Date() });
    await presentation.save();

    res.json(presentation);
  } catch (error: unknown) {
    const err = error as Error;
    console.error('[Presentation Update Error]', err?.message || err);
    res.status(500).json({ error: 'Failed to update presentation', details: err?.message });
  }
});

// Delete presentation
router.delete('/:id', requirePermission('presentations', 'delete'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { Presentation } = getModels();

    const presentation = await Presentation.findById(id);
    if (!presentation) {
      res.status(404).json({ error: 'Presentation not found' });
      return;
    }

    if (!req.user!.companyIds.includes(presentation.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    await Presentation.findByIdAndDelete(id);
    res.json({ message: 'Presentation deleted successfully' });
  } catch (error) {
    console.error('[Presentation Delete Error]', error);
    res.status(500).json({ error: 'Failed to delete presentation' });
  }
});

// Duplicate presentation
router.post('/:id/duplicate', requirePermission('presentations', 'manage'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { Presentation } = getModels();

    const original = await Presentation.findById(id);
    if (!original) {
      res.status(404).json({ error: 'Presentation not found' });
      return;
    }

    if (!req.user!.companyIds.includes(original.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    const duplicate = new Presentation({
      ...original.toObject(),
      _id: undefined,
      title: `${original.title} (Copy)`,
      status: 'draft',
      version: 1,
      previousVersions: [],
      createdBy: req.user!._id,
      createdAt: new Date(),
      updatedAt: new Date(),
    });
    await duplicate.save();

    res.status(201).json(duplicate);
  } catch (error) {
    console.error('[Presentation Duplicate Error]', error);
    res.status(500).json({ error: 'Failed to duplicate presentation' });
  }
});

// ============================================
// SLIDE MANAGEMENT
// ============================================

// Reorder slides
router.put('/:id/reorder', requirePermission('presentations', 'edit'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { slides } = req.body;
    const { Presentation } = getModels();

    const presentation = await Presentation.findById(id);
    if (!presentation) {
      res.status(404).json({ error: 'Presentation not found' });
      return;
    }

    if (!req.user!.companyIds.includes(presentation.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    const orderedSlides = slides.map((s: Record<string, unknown>, index: number) => ({
      ...s,
      order: index,
    }));
    presentation.slides = orderedSlides;
    presentation.updatedAt = new Date();
    await presentation.save();

    res.json(presentation);
  } catch (error) {
    console.error('[Presentation Reorder Error]', error);
    res.status(500).json({ error: 'Failed to reorder slides' });
  }
});

// Regenerate single slide with AI
router.post('/:id/slides/:slideId/regenerate', requirePermission('presentations', 'ai-generate'), async (req: Request, res: Response) => {
  try {
    const { id, slideId } = req.params;
    const { contextData, customInstructions } = req.body;
    const { Presentation } = getModels();

    const presentation = await Presentation.findById(id);
    if (!presentation) {
      res.status(404).json({ error: 'Presentation not found' });
      return;
    }

    if (!req.user!.companyIds.includes(presentation.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    const slideIndex = presentation.slides.findIndex((s: any) => s.id === slideId);
    if (slideIndex === -1) {
      res.status(404).json({ error: 'Slide not found' });
      return;
    }

    // TODO: Call AI generation service here
    // const generatedContent = await aiService.generateSlideContent(presentation, slideIndex, contextData);

    // For now, return placeholder
    res.json({
      message: 'AI regeneration endpoint - to be implemented',
      slideId,
      presentationId: id,
    });
  } catch (error) {
    console.error('[Slide Regenerate Error]', error);
    res.status(500).json({ error: 'Failed to regenerate slide' });
  }
});

// ============================================
// AI GENERATION
// ============================================

// Generate brief content for presentation (called before creating presentation)
router.post(
  '/generate-brief',
  requirePermission('presentations', 'ai-generate'),
  async (req: Request, res: Response) => {
    // The wizard's "Generate with AI" ran without opening a job, so Presentations
    // reached neither the completion notification nor the completion email that
    // every job-based module gets. Declared out here so the catch can fail it.
    let aiJob: { jobId: string } | null = null;
    try {
      const { type, title, description, tone, templateStyle, selectedSlides, numberOfSlides, dataSource, companyId, language } = req.body;

      if (!type || !description) {
        res.status(400).json({ error: 'Presentation type and description are required' });
        return;
      }

      // Check company access
      if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
        res.status(403).json({ error: 'Access denied' });
        return;
      }

      const { BusinessProfile, Founder, Product, Employee, Course, Event } = getModels();

      // Fetch data sources if provided
      let contextData: Record<string, unknown> = {};
      if (dataSource) {
        const dataFetches: Promise<unknown>[] = [];
        const dataKeys: string[] = [];

        if (dataSource.businessProfileId) {
          dataFetches.push(BusinessProfile.findOne({ companyId }).exec());
          dataKeys.push('businessProfile');
        }
        if (dataSource.founderIds?.length) {
          dataFetches.push(Founder.find({ companyId, _id: { $in: dataSource.founderIds } }).exec());
          dataKeys.push('founders');
        }
        if (dataSource.employeeIds?.length) {
          dataFetches.push(Employee.find({ companyId, _id: { $in: dataSource.employeeIds } }).exec());
          dataKeys.push('employees');
        }
        if (dataSource.productIds?.length) {
          dataFetches.push(Product.find({ companyId, _id: { $in: dataSource.productIds } }).exec());
          dataKeys.push('products');
        }

        const results = await Promise.all(dataFetches);
        results.forEach((result, index) => {
          contextData[dataKeys[index]] = result;
        });
      }

      // Template style guidance
      const templateStyles: Record<string, { name: string; guidance: string }> = {
        modern: {
          name: 'Modern',
          guidance: 'Use clean, minimal formatting with bold headings and concise bullet points. Focus on key insights and impactful statements.'
        },
        corporate: {
          name: 'Corporate',
          guidance: 'Use structured, formal language with detailed explanations and clear sections. Professional terminology and thorough coverage.'
        },
        creative: {
          name: 'Creative',
          guidance: 'Use bold, engaging language with punchy, memorable phrases. Eye-catching headlines and impactful statements. Make it exciting and memorable.'
        },
        minimal: {
          name: 'Minimal',
          guidance: 'Use essential information only with very brief bullet points. Clean and simple language. Less is more approach.'
        },
        storytelling: {
          name: 'Storytelling',
          guidance: 'Use narrative flow with compelling story-like progression. Connect ideas with engaging transitions. Create an emotional journey.'
        }
      };
      const selectedTemplate = templateStyles[templateStyle] || templateStyles.modern;

      // Build prompt for AI - use selected slides or default based on numberOfSlides
      const defaultSlides = getDefaultSlidesForType(type);
      const slideCount = numberOfSlides || selectedSlides?.length || 8;
      const slidesToGenerate = selectedSlides && selectedSlides.length > 0
        ? selectedSlides
        : defaultSlides.slice(0, slideCount);

      const systemPrompt = `You are an expert presentation content creator creating comprehensive, engaging slide content for a ${type} presentation.

Title: "${title}"
Tone: ${tone || 'professional'}
Template Style: ${selectedTemplate.name} - ${selectedTemplate.guidance}

Create DETAILED, RICH slide content that fills presentation slides with meaningful information.

FORMATTING RULES:
- NO markdown headers (## or ###) - use plain text only
- Use a SINGLE bullet point (•) at the start of each line - NEVER use double bullets (••)
- Each slide should have a clear TITLE line first, then 6-8 content lines
- Use bold text (**like this**) for emphasis on key terms
- Add context and depth - each bullet should be informative
- Keep total content to 8-12 lines per slide for a full, rich slide

IMPORTANT CONTENT RULES:
- DO NOT make up fake metrics, numbers, or statistics
- DO NOT invent client names, awards, or achievements
- Use generic but meaningful phrases when specific data is unavailable
- Only include information that is relevant to the presentation topic
- Use the provided description and data sources for real context
- If you don't have specific information, use descriptive but generic language
- Match the template style: ${selectedTemplate.guidance}

CONTENT STRUCTURE PER SLIDE:
Line 1: Clear slide title (plain text, no bullet)
Lines 2+: Content lines with single bullet (•)

Example format:
"About Company": "About Our Company\\n\\n• Company mission and vision\\n• Core values and principles\\n• Industry expertise and focus\\n• Customer success commitment\\n• Innovation and quality focus\\n• Team dedication\\n• Market position"`;

      const userPrompt = `Create comprehensive presentation content for these ${slidesToGenerate.length} slides:

Type: ${type}
Title: ${title}
Tone: ${tone || 'professional'}
Description: ${description}
${Object.keys(contextData).length > 0 ? `\nConnected Data:\n${JSON.stringify(contextData, null, 2).slice(0, 2000)}` : ''}

Slides to generate:
${slidesToGenerate.map((s: string, i: number) => `${i + 1}. ${s}`).join('\n')}

For each slide, create RICH, DETAILED content with 6-8 bullet points.

IMPORTANT CONTENT RULES:
- Use SINGLE bullet point (•) at start of each line - NEVER double bullets (••)
- Do NOT make up fake metrics, numbers, or statistics
- Do NOT invent client names, awards, or achievements
- Use the description and data provided for context
- Be descriptive but honest when specific data is unavailable
- Use generic but meaningful language when needed

Return JSON with slide titles as keys. Each slide content should have:
- A clear title on the first line
- 6-8 detailed bullet points with SINGLE bullet (•) per line
- NO double bullets (••)
- Bold text for key terms using ** **

Example:
{
  "Title Slide": "Company Name\\n\\n• Value proposition\\n• Presentation overview\\n• Key focus area\\n• Main theme\\n• Brief agenda",
  "About Company": "About Our Company\\n\\n• Company mission\\n• Core values\\n• Industry expertise\\n• Customer focus\\n• Innovation commitment\\n• Team dedication\\n• Quality focus"
}`;

      // Append language instruction to system prompt
      const languageInstruction = buildLanguageInstruction(language);
      const finalSystemPrompt = systemPrompt + languageInstruction;

      // Call AI generation service — use Ollama locally for reliable generation
      // (cloud providers may be unavailable/expired; Ollama runs locally and always works)
      const { generateWithAI } = require('../utils/aiProvider');
      aiJob = createJob('presentation-generator', companyId);
      const result = await generateWithAI(userPrompt, finalSystemPrompt, 12000, undefined, 'json', 'ollama', undefined, undefined, undefined, true);

      if (!result || !result.content) {
        res.status(500).json({ error: 'AI generation failed. Please try again.' });
        return;
      }

      // Parse AI response
      let briefContent: Record<string, string> = {};
      try {
        // Try to parse as JSON
        const parsed = JSON.parse(result.content);
        briefContent = parsed;
      } catch {
        // If not valid JSON, try to extract sections from text
        const lines = result.content.split('\n');
        let currentSlide = '';
        let currentContent: string[] = [];

        for (const line of lines) {
          // Check if this is a slide title (slides to generate)
          const matchedSlide = slidesToGenerate.find((s: string) =>
            line.toLowerCase().includes(s.toLowerCase()) || s.toLowerCase().includes(line.toLowerCase())
          );

          if (matchedSlide && line.trim()) {
            if (currentSlide && currentContent.length > 0) {
              briefContent[currentSlide] = currentContent.join('\n').trim();
            }
            currentSlide = matchedSlide;
            currentContent = [];
          } else if (currentSlide) {
            currentContent.push(line);
          }
        }

        // Add last slide
        if (currentSlide && currentContent.length > 0) {
          briefContent[currentSlide] = currentContent.join('\n').trim();
        }

        // Fallback: create placeholder for any missing slides
        for (const slide of slidesToGenerate) {
          if (!briefContent[slide]) {
            briefContent[slide] = `Content for ${slide}`;
          }
        }
      }

      // After the content is built, so a generation that threw never reports
      // success. completeJob raises the in-app notification and the completion
      // email, both subject to the user's AI generation preferences.
      completeJob(aiJob.jobId, { title: title || '' }, 'presentation-generator');

      res.json({
        briefContent,
        slides: slidesToGenerate,
        tokensUsed: result.tokenUsage?.totalTokens ?? 0,
        provider: result.provider,
        language: language || 'en',
      });
    } catch (error) {
      console.error('[Presentation Generate Brief Error]', error);
      if (aiJob) failJob(aiJob.jobId, error instanceof Error ? error.message : 'Unknown error');
      res.status(500).json({ error: 'Failed to generate brief content' });
    }
  }
);

// Helper function to get default slides for presentation type
function getDefaultSlidesForType(type: string): string[] {
  const slideTemplates: Record<string, string[]> = {
    'company-profile': ['Title Slide', 'About Company', 'Vision & Mission', 'Products & Services', 'Team', 'Achievements', 'Case Studies', 'Client Portfolio', 'Contact Information'],
    'product': ['Title Slide', 'Problem Statement', 'Solution', 'Key Features', 'Benefits', 'Use Cases', 'Pricing', 'Competitive Advantage', 'Customer Testimonials', 'Call to Action'],
    'investor-pitch': ['Title Slide', 'Problem', 'Solution', 'Market Opportunity', 'Business Model', 'Traction', 'Revenue Model', 'Competitor Analysis', 'MOAT Summary', 'Financial Overview', 'Funding Ask', 'Roadmap'],
    'event-outdoor': ['Title Slide', 'Event Introduction', 'Objective', 'Brand Message', 'Sponsorship Proposal', 'Exhibition Details', 'Partnership Offer', 'Marketing Campaign', 'Call to Action'],
    'sales-pitch': ['Title Slide', 'Opening Hook', 'Pain Points', 'Value Proposition', 'Product Demo', 'ROI & Benefits', 'Pricing Options', 'Success Stories', 'Objection Handling', 'Call to Action', 'Next Steps'],
    'marketing-campaign': ['Title Slide', 'Campaign Overview', 'Objectives & Goals', 'Target Audience', 'Strategy', 'Channels & Tactics', 'Budget Allocation', 'Timeline', 'Expected Results', 'Measurement & KPIs', 'Team & Resources'],
    'training-onboarding': ['Title Slide', 'Welcome & Introduction', 'Company Overview', 'Mission & Values', 'Organizational Structure', 'Policies & Procedures', 'Tools & Resources', 'Team Introduction', 'Role Responsibilities', 'First Week Goals', 'Support & Contacts'],
    'quarterly-review': ['Title Slide', 'Executive Summary', 'Key Metrics', 'Revenue & Growth', 'Customer Highlights', 'Product Updates', 'Team Achievements', 'Challenges', 'Lessons Learned', 'Next Quarter Goals', 'Q&A'],
    'project-proposal': ['Title Slide', 'Executive Summary', 'Problem Statement', 'Proposed Solution', 'Project Scope', 'Timeline & Milestones', 'Budget', 'Team Requirements', 'Risk Assessment', 'Expected Outcomes', 'Success Metrics', 'Next Steps'],
    'partnership-proposal': ['Title Slide', 'Company Introduction', 'Partnership Opportunity', 'Mutual Benefits', 'Collaboration Model', 'Resource Requirements', 'Timeline', 'Success Stories', 'Terms & Conditions', 'Call to Action'],
    'investor-update': ['Title Slide', 'Executive Summary', 'Key Highlights', 'Financial Update', 'Product Development', 'Team Growth', 'Market Updates', 'Customer Traction', 'Challenges & Mitigations', 'Ask & Next Steps', 'Q&A'],
    'product-launch': ['Title Slide', 'The Big Reveal', 'Problem We Solve', 'Product Overview', 'Key Features', 'Demo', 'Pricing & Availability', 'Go-to-Market Strategy', 'Success Stories', 'Press & Media', 'Call to Action'],
    'case-study': ['Title Slide', 'Client Overview', 'Challenge', 'Our Approach', 'Solution Implemented', 'Timeline', 'Results & Metrics', 'Testimonials', 'Key Learnings', 'Why It Matters'],
  };
  return slideTemplates[type] || slideTemplates['company-profile'];
}

// Generate slides with AI (background job)
router.post(
  '/generate-slides',
  requireRole('admin', 'editor'),
  async (req: Request, res: Response) => {
    try {
      const { presentationId, type, title, description, tone, slides, companyId, briefContent } = req.body;

      if (!presentationId || !companyId) {
        res.status(400).json({ error: 'Presentation ID and Company ID are required' });
        return;
      }

      // Check company access
      if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
        res.status(403).json({ error: 'Access denied' });
        return;
      }

      const { Presentation, BackgroundTask } = getModels();

      // Create background task for slide generation
      const task = new BackgroundTask({
        type: 'ai-generation',
        module: 'presentations',
        action: 'generate-slides',
        companyId,
        userId: req.user!._id,
        status: 'pending',
        input: {
          presentationId,
          type,
          title,
          description,
          tone,
          slides,
          briefContent,
        },
        priority: 5,
      });

      await task.save();

      // Start processing in background
      processSlideGeneration(task._id.toString()).catch(console.error);

      res.json({
        taskId: task._id,
        message: 'Slide generation started',
      });
    } catch (error) {
      console.error('[Generate Slides Error]', error);
      res.status(500).json({ error: 'Failed to start slide generation' });
    }
  }
);

// Background processing function for slide generation
async function processSlideGeneration(taskId: string) {
  const { Presentation, BackgroundTask } = getModels();

  try {
    const task = await BackgroundTask.findById(taskId);
    if (!task) return;

    // Update status to processing
    task.status = 'processing';
    task.startedAt = new Date();
    await task.save();

    const { presentationId, type, title, description, tone, slides, briefContent, companyId } = task.input as Record<string, unknown>;

    // Fetch presentation
    const presentation = await Presentation.findById(presentationId);
    if (!presentation) {
      throw new Error('Presentation not found');
    }

    // Build system prompt for slide generation
    const systemPrompt = `You are an expert presentation designer. Generate detailed, professional slide content for a ${type} presentation.
The presentation title is: "${title}"
Tone: ${tone || 'professional'}

For each slide, create content that:
- Is visually structured and scannable
- Uses clear headlines and bullet points
- Includes relevant data and metrics
- Matches the presentation tone
- Is ready to be displayed on a slide`;

    // Build prompt with all slides
    const slidePrompts = (slides as Array<{ title: string; content: string }>).map((slide, index) =>
      `SLIDE ${index + 1}: ${slide.title}\nBrief content: ${slide.content || (briefContent as any)?.[slide.title] || 'Generate appropriate content'}`
    ).join('\n\n');

    const userPrompt = `Generate detailed content for each of these ${(slides as any[]).length} slides:

${slidePrompts}

For each slide, provide:
1. A clear headline (improving the slide title if needed)
2. 3-5 key bullet points or structured content
3. Any relevant data points or metrics
4. Optional speaker notes

Format your response as JSON:
{
  "slides": [
    {
      "id": "slide-1",
      "order": 0,
      "title": "Slide Title",
      "content": "Main content text",
      "bullets": ["Point 1", "Point 2", "Point 3"],
      "notes": "Speaker notes...",
      "layout": "default"
    },
    ...
  ]
}`;

    // Call AI generation service — use Ollama locally for reliable generation
    const { generateWithAI } = require('../utils/aiProvider');
    const result = await generateWithAI(userPrompt, systemPrompt, 10000, undefined, 'json', 'ollama', undefined, undefined, undefined, true);

    if (!result || !result.content) {
      throw new Error('AI generation failed');
    }

    // Parse AI response
    let generatedSlides: Array<Record<string, unknown>> = [];
    try {
      const parsed = JSON.parse(result.content);
      generatedSlides = parsed.slides || [];
    } catch {
      // Try to extract slides from text
      const lines = result.content.split('\n');
      let currentSlide: Record<string, unknown> | null = null;

      for (const line of lines) {
        if (line.match(/^SLIDE\s+\d+:/i) || line.match(/^slide\s*\d+/i)) {
          if (currentSlide) generatedSlides.push(currentSlide);
          currentSlide = { title: line.replace(/^SLIDE\s*\d*:\s*/i, ''), content: '', bullets: [] };
        } else if (currentSlide) {
          if (line.trim().startsWith('-') || line.trim().startsWith('•')) {
            (currentSlide.bullets as string[]).push(line.trim().replace(/^[-•]\s*/, ''));
          } else {
            currentSlide.content = (currentSlide.content as string) + '\n' + line;
          }
        }
      }
      if (currentSlide) generatedSlides.push(currentSlide);
    }

    // Update presentation with generated slides
    presentation.slides = generatedSlides.map((slide, index) => ({
      id: `slide-${Date.now()}-${index}`,
      order: index,
      title: slide.title || `Slide ${index + 1}`,
      content: slide.content || '',
      bullets: slide.bullets || [],
      notes: slide.notes || '',
      layout: slide.layout || 'default',
      aiGenerated: true,
    }));

    presentation.status = 'draft';
    presentation.updatedAt = new Date();
    await presentation.save();

    // Update task status
    task.status = 'completed';
    task.completedAt = new Date();
    task.result = {
      slidesGenerated: generatedSlides.length,
      presentationId,
    };
    await task.save();

  } catch (error) {
    console.error('[Slide Generation Process Error]', error);

    // Update task with error
    const task = await BackgroundTask.findById(taskId);
    if (task) {
      task.status = 'failed';
      task.error = error instanceof Error ? error.message : 'Unknown error';
      task.completedAt = new Date();
      await task.save();
    }
  }
}

// Generate full presentation with AI
router.post('/:id/generate', requirePermission('presentations', 'ai-generate'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { promptConfigId } = req.body;
    const { Presentation, BusinessProfile, Founder, Product, ICP, Competitor } = getModels();

    const presentation = await Presentation.findById(id);
    if (!presentation) {
      res.status(404).json({ error: 'Presentation not found' });
      return;
    }

    if (!req.user!.companyIds.includes(presentation.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    // Fetch linked data
    const companyId = presentation.companyId;
    const [businessProfile, founders, products, icps, competitors] = await Promise.all([
      BusinessProfile.findOne({ companyId }),
      Founder.find({ companyId }),
      Product.find({ companyId }),
      ICP.find({ companyId }),
      Competitor.find({ companyId }),
    ]);

    // TODO: Call AI generation service
    // Build context and generate slides based on presentation type

    res.json({
      message: 'AI generation endpoint - to be implemented',
      presentationId: id,
      context: {
        businessProfile,
        founders,
        products,
        icps,
        competitors,
      }
    });
  } catch (error) {
    console.error('[Presentation Generate Error]', error);
    res.status(500).json({ error: 'Failed to generate presentation' });
  }
});

// ============================================
// VERSION HISTORY
// ============================================

// Get version history
router.get('/:id/versions', async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { Presentation } = getModels();

    const presentation = await Presentation.findById(id);
    if (!presentation) {
      res.status(404).json({ error: 'Presentation not found' });
      return;
    }

    if (!req.user!.companyIds.includes(presentation.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    res.json({
      currentVersion: presentation.version,
      versions: presentation.previousVersions || [],
    });
  } catch (error) {
    console.error('[Presentation Versions Error]', error);
    res.status(500).json({ error: 'Failed to get version history' });
  }
});

// Restore version
router.post('/:id/restore/:version', requirePermission('presentations', 'manage'), async (req: Request, res: Response) => {
  try {
    const { id, version } = req.params;
    const { Presentation } = getModels();

    const presentation = await Presentation.findById(id);
    if (!presentation) {
      res.status(404).json({ error: 'Presentation not found' });
      return;
    }

    if (!req.user!.companyIds.includes(presentation.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    const versionNum = parseInt(version, 10);
    const historicalVersion = presentation.previousVersions?.find((v: any) => v.version === versionNum);

    if (!historicalVersion) {
      res.status(404).json({ error: 'Version not found' });
      return;
    }

    // Save current state before restore
    const currentVersion = {
      version: presentation.version,
      slides: presentation.slides,
      savedAt: new Date(),
      savedBy: req.user!._id,
      changeLog: 'Pre-restore backup',
    };
    presentation.previousVersions = presentation.previousVersions || [];
    presentation.previousVersions.push(currentVersion);

    // Restore the historical version
    presentation.slides = historicalVersion.slides;
    presentation.version = (presentation.version || 1) + 1;
    presentation.updatedAt = new Date();
    await presentation.save();

    res.json(presentation);
  } catch (error) {
    console.error('[Presentation Restore Error]', error);
    res.status(500).json({ error: 'Failed to restore version' });
  }
});

// ============================================
// EXPORT
// ============================================

// Export presentation
router.post('/:id/export', requirePermission('presentations', 'export'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { format } = req.body;
    const { Presentation } = getModels();

    const presentation = await Presentation.findById(id);
    if (!presentation) {
      res.status(404).json({ error: 'Presentation not found' });
      return;
    }

    if (!req.user!.companyIds.includes(presentation.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    // Update export settings
    presentation.exportSettings = {
      ...presentation.exportSettings,
      format: format || 'pdf',
      lastExportedAt: new Date(),
    };
    await presentation.save();

    // Return presentation data for client-side export
    res.json({
      presentation,
      exportFormat: format || 'pdf',
    });
  } catch (error) {
    console.error('[Presentation Export Error]', error);
    res.status(500).json({ error: 'Failed to export presentation' });
  }
});

export default router;