/**
 * Speaking Engagement Routes
 * CRUD operations for speaking engagements with filtering, validation, and role-based access
 */

import express, { Request, Response } from 'express';
import { body, validationResult } from 'express-validator';
import { getModels } from '../models';
import { authenticateJwtOrApiToken } from '../middleware/dualAuth';
import { requirePermission } from '../middleware/permissions';

const router = express.Router();

router.use(authenticateJwtOrApiToken);

// ============================================
// GET ALL SPEAKING ENGAGEMENTS FOR A COMPANY
// ============================================

router.get('/:companyId', async (req: Request, res: Response) => {
  try {
    const { companyId } = req.params;
    const { SpeakingEngagement } = getModels();

    // Authorization check
    if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    // Build filter query
    const filter: Record<string, any> = { companyId };

    // Optional filters
    if (req.query.speechType) {
      filter.speechType = req.query.speechType;
    }
    if (req.query.status) {
      filter.status = req.query.status;
    }
    if (req.query.language) {
      filter.language = req.query.language;
    }
    if (req.query.speakerType) {
      filter.speakerType = req.query.speakerType;
    }
    if (req.query.tone) {
      filter.tone = req.query.tone;
    }
    if (req.query.source) {
      filter.source = req.query.source;
    }

    // Search functionality
    if (req.query.search) {
      const searchRegex = new RegExp(req.query.search as string, 'i');
      filter.$or = [
        { name: searchRegex },
        { content: searchRegex },
        { topic: searchRegex },
      ];
    }

    const speeches = await SpeakingEngagement.find(filter).sort({ createdAt: -1 });
    res.json(speeches);
  } catch (error) {
    console.error('Error fetching speaking engagements:', error);
    res.status(500).json({ error: 'Failed to get speaking engagements' });
  }
});

// ============================================
// GET SINGLE SPEAKING ENGAGEMENT
// ============================================

router.get('/detail/:id', async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { SpeakingEngagement } = getModels();

    const speech = await SpeakingEngagement.findById(id);
    if (!speech) {
      res.status(404).json({ error: 'Speaking engagement not found' });
      return;
    }

    // Authorization check
    if (!req.user!.companyIds.includes(speech.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    res.json(speech);
  } catch (error) {
    console.error('Error fetching speaking engagement:', error);
    res.status(500).json({ error: 'Failed to get speaking engagement' });
  }
});

// ============================================
// CREATE SPEAKING ENGAGEMENT
// ============================================

router.post(
  '/',
  requirePermission('speaking-engagements', 'create'),
  [
    body('companyId').notEmpty().withMessage('Company ID is required'),
    body('name').trim().notEmpty().withMessage('Speech name is required'),
    body('speechType').isIn([
      'tedx-speech', 'josh-talks-speech', 'one-line-speech', 'storytelling-speech',
      'elevator-pitch', 'keynote-speech', 'event-speech', 'motivational-speech',
      'company-introduction', 'founder-introduction', 'employee-introduction',
      'product-launch-speech', 'award-acceptance', 'investor-pitch-speech',
      'networking-introduction', 'custom-speech',
    ]).withMessage('Invalid speech type'),
    // Content is optional for drafts — required for non-draft statuses
    body('content').if((value, { req }) => req.body.status !== 'draft').trim().notEmpty().withMessage('Speech content is required for non-draft speeches'),
    body('content').if((value, { req }) => req.body.status === 'draft').optional({ checkFalsy: true }).trim(),
    body('language').optional().isIn([
      'en', 'hi', 'mr', 'es', 'fr', 'de', 'pt', 'it', 'nl', 'ru',
      'ja', 'ko', 'zh', 'ar', 'tr', 'pl', 'sv', 'no', 'da', 'fi',
      'cs', 'el', 'he', 'th', 'vi', 'id', 'ms', 'fil', 'bn', 'ur',
      'ta', 'te', 'kn', 'ml', 'pa', 'gu', 'sw', 'am',
    ]),
    body('duration').optional().isIn(['30s', '1min', '2min', '3min', '5min', '10min', '15min', '20min', '30min', '45min', '1hr', '2hr-plus']),
    body('speakerType').optional().isIn(['founder', 'employee', 'ceo', 'manager', 'other']),
    body('tone').optional().isIn([
      'professional', 'inspirational', 'motivational', 'emotional', 'humorous',
      'formal', 'friendly', 'corporate', 'casual', 'storytelling',
    ]),
    body('source').optional().isIn(['ai-generation', 'manual']),
    body('status').optional().isIn(['draft', 'review', 'approved', 'published', 'archived']),
  ],
  async (req: Request, res: Response) => {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        res.status(400).json({ errors: errors.array() });
        return;
      }

      // Authorization check
      if (!req.user!.companyIds.includes(req.body.companyId) && req.user!.role !== 'admin') {
        res.status(403).json({ error: 'Access denied' });
        return;
      }

      const { SpeakingEngagement } = getModels();

      const speechData = {
        ...req.body,
        status: req.body.status || 'draft',
        source: req.body.source || 'manual',
        language: req.body.language || 'en',
        duration: req.body.duration || '2min',
        speakerType: req.body.speakerType || 'founder',
        tone: req.body.tone || 'professional',
        version: req.body.version || 1,
      };

      const speech = new SpeakingEngagement(speechData);
      await speech.save();

      res.status(201).json(speech);
    } catch (error) {
      console.error('Error creating speaking engagement:', error);
      res.status(500).json({ error: 'Failed to create speaking engagement' });
    }
  }
);

// ============================================
// UPDATE SPEAKING ENGAGEMENT
// ============================================

router.put('/:id', requirePermission('speaking-engagements', 'edit'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { SpeakingEngagement } = getModels();

    const speech = await SpeakingEngagement.findById(id);
    if (!speech) {
      res.status(404).json({ error: 'Speaking engagement not found' });
      return;
    }

    // Authorization check
    if (!req.user!.companyIds.includes(speech.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    Object.assign(speech, req.body, { updatedAt: new Date().toISOString() });
    await speech.save();

    res.json(speech);
  } catch (error) {
    console.error('Error updating speaking engagement:', error);
    res.status(500).json({ error: 'Failed to update speaking engagement' });
  }
});

// ============================================
// DELETE SPEAKING ENGAGEMENT
// ============================================

router.delete('/:id', requirePermission('speaking-engagements', 'delete'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { SpeakingEngagement } = getModels();

    const speech = await SpeakingEngagement.findById(id);
    if (!speech) {
      res.status(404).json({ error: 'Speaking engagement not found' });
      return;
    }

    // Authorization check
    if (!req.user!.companyIds.includes(speech.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    await SpeakingEngagement.findByIdAndDelete(id);
    res.json({ message: 'Speaking engagement deleted successfully' });
  } catch (error) {
    console.error('Error deleting speaking engagement:', error);
    res.status(500).json({ error: 'Failed to delete speaking engagement' });
  }
});

// ============================================
// CLEAR ALL SPEAKING ENGAGEMENTS FOR A COMPANY
// ============================================

router.delete('/clear/:companyId', requirePermission('speaking-engagements', 'delete'), async (req: Request, res: Response) => {
  try {
    const { companyId } = req.params;
    const { SpeakingEngagement } = getModels();

    // Authorization check
    if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    // Optional filter by speechType
    const filter: Record<string, any> = { companyId };
    if (req.query.speechType) {
      filter.speechType = req.query.speechType;
    }

    const result = await SpeakingEngagement.deleteMany(filter);
    res.json({ message: `Deleted ${result.deletedCount} speaking engagements`, deletedCount: result.deletedCount });
  } catch (error) {
    console.error('Error clearing speaking engagements:', error);
    res.status(500).json({ error: 'Failed to clear speaking engagements' });
  }
});

export default router;