/**
 * Email Template Routes
 *
 * CRUD + categories + AI generation for email templates.
 */

import express, { Request, Response } from 'express';
import { body, param, query, validationResult } from 'express-validator';
import { getModels } from '../models';
import { authenticate } from '../middleware/auth';
import { requirePermission } from '../middleware/permissions';
import { generateWithAI } from '../utils/aiProvider';
import { createJob, completeJob, failJob } from '../services/aiContext/aiJobManager';

const router = express.Router();
router.use(authenticate);

// ============================================
// CATEGORY ROUTES
// ============================================

router.get('/categories/:companyId', async (req: Request, res: Response) => {
  try {
    const { EmailTemplateCategory } = getModels();
    const categories = await EmailTemplateCategory.find({ companyId: req.params.companyId }).sort({ order: 1, name: 1 });
    res.json({ data: categories });
  } catch (error: any) {
    res.status(500).json({ error: error.message });
  }
});

router.post('/categories',
  requirePermission('email-templates', 'create'),
  body('name').trim().notEmpty().withMessage('Category name is required'),
  body('companyId').notEmpty().withMessage('Company ID is required'),
  async (req: Request, res: Response) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) return res.status(400).json({ error: errors.array() });
    try {
      const { EmailTemplateCategory } = getModels();
      const category = new EmailTemplateCategory(req.body);
      await category.save();
      res.status(201).json({ data: category });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

router.put('/categories/:id', requirePermission('email-templates', 'edit'), async (req: Request, res: Response) => {
  try {
    const { EmailTemplateCategory } = getModels();
    const category = await EmailTemplateCategory.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
    if (!category) return res.status(404).json({ error: 'Category not found' });
    res.json({ data: category });
  } catch (error: any) {
    res.status(500).json({ error: error.message });
  }
});

router.delete('/categories/:id', requirePermission('email-templates', 'delete'), async (req: Request, res: Response) => {
  try {
    const { EmailTemplate, EmailTemplateCategory } = getModels();
    const templatesInCategory = await EmailTemplate.countDocuments({ category: req.params.id });
    if (templatesInCategory > 0) {
      return res.status(400).json({ error: 'Cannot delete category with existing templates. Reassign templates first.' });
    }
    const category = await EmailTemplateCategory.findByIdAndDelete(req.params.id);
    if (!category) return res.status(404).json({ error: 'Category not found' });
    res.json({ data: { message: 'Category deleted' } });
  } catch (error: any) {
    res.status(500).json({ error: error.message });
  }
});

// ============================================
// EMAIL TEMPLATE CRUD
// ============================================

router.get('/:companyId', async (req: Request, res: Response) => {
  try {
    const { EmailTemplate } = getModels();
    const { search, type, category, status, sort, page = '1', limit = '20' } = req.query;
    const filter: any = { companyId: req.params.companyId };
    if (search) filter.$or = [{ name: { $regex: search, $options: 'i' } }, { subjectLine: { $regex: search, $options: 'i' } }];
    if (type) filter.type = type;
    if (category) filter.category = category;
    if (status) filter.status = status;

    const pageNum = parseInt(page as string, 10);
    const limitNum = parseInt(limit as string, 10);
    const skip = (pageNum - 1) * limitNum;

    const [templates, total] = await Promise.all([
      EmailTemplate.find(filter).sort(sort ? String(sort) : '-updatedAt').skip(skip).limit(limitNum),
      EmailTemplate.countDocuments(filter),
    ]);

    res.json({ data: templates, pagination: { page: pageNum, limit: limitNum, total, pages: Math.ceil(total / limitNum) } });
  } catch (error: any) {
    res.status(500).json({ error: error.message });
  }
});

router.get('/detail/:id', async (req: Request, res: Response) => {
  try {
    const { EmailTemplate } = getModels();
    const template = await EmailTemplate.findById(req.params.id);
    if (!template) return res.status(404).json({ error: 'Template not found' });
    res.json({ data: template });
  } catch (error: any) {
    res.status(500).json({ error: error.message });
  }
});

router.post('/',
  requirePermission('email-templates', 'create'),
  body('name').trim().notEmpty().withMessage('Template name is required'),
  body('companyId').notEmpty().withMessage('Company ID is required'),
  body('type').notEmpty().withMessage('Email type is required'),
  body('subjectLine').trim().notEmpty().withMessage('Subject line is required'),
  async (req: Request, res: Response) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) return res.status(400).json({ error: errors.array() });
    try {
      const { EmailTemplate } = getModels();
      const template = new EmailTemplate(req.body);
      await template.save();
      res.status(201).json({ data: template });
    } catch (error: any) {
      res.status(500).json({ error: error.message });
    }
  }
);

router.put('/:id', requirePermission('email-templates', 'edit'), async (req: Request, res: Response) => {
  try {
    const { EmailTemplate } = getModels();
    const template = await EmailTemplate.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
    if (!template) return res.status(404).json({ error: 'Template not found' });
    res.json({ data: template });
  } catch (error: any) {
    res.status(500).json({ error: error.message });
  }
});

router.delete('/:id', requirePermission('email-templates', 'delete'), async (req: Request, res: Response) => {
  try {
    const { EmailTemplate } = getModels();
    const template = await EmailTemplate.findByIdAndDelete(req.params.id);
    if (!template) return res.status(404).json({ error: 'Template not found' });
    res.json({ data: { message: 'Template deleted' } });
  } catch (error: any) {
    res.status(500).json({ error: error.message });
  }
});

router.post('/:id/duplicate', requirePermission('email-templates', 'manage'), async (req: Request, res: Response) => {
  try {
    const { EmailTemplate } = getModels();
    const original = await EmailTemplate.findById(req.params.id);
    if (!original) return res.status(404).json({ error: 'Template not found' });
    const duplicate = new EmailTemplate({
      ...original.toObject(),
      _id: undefined,
      name: `${original.name} (Copy)`,
      status: 'draft',
      createdAt: undefined,
      updatedAt: undefined,
    });
    await duplicate.save();
    res.status(201).json({ data: duplicate });
  } catch (error: any) {
    res.status(500).json({ error: error.message });
  }
});

// ============================================
// AI GENERATION
// ============================================

router.post('/ai/generate', requirePermission('email-templates', 'ai-generate'), async (req: Request, res: Response) => {
  // Email Templates generated without opening a job, so it reached neither the
  // completion notification nor the completion email. Declared out here so the
  // catch below can fail the job.
  let aiJob: { jobId: string } | null = null;
  try {
    const { emailType, audience, purpose, tone, length, ctaGoal, context, language } = req.body;
    if (!emailType || !purpose) {
      return res.status(400).json({ error: 'emailType and purpose are required' });
    }

    const systemPrompt = `You are an expert email marketing copywriter. You create compelling, professional email templates. Always respond with valid JSON only. No markdown, no explanation — just the JSON object.${language && language !== 'English' ? ` Generate all text content in ${language}.` : ''}`;

    const userPrompt = `Generate an email template with these requirements:
- Email Type: ${emailType}
- Target Audience: ${audience || 'General audience'}
- Purpose: ${purpose}
- Tone: ${tone || 'professional'}
- Length: ${length || 'medium'}
- CTA Goal: ${ctaGoal || 'Learn More'}
${context ? `- Additional Context: ${context}` : ''}
${language && language !== 'English' ? `- Language: ${language} — Generate all text (name, subject line, preview text, body, CTA) in ${language}.` : ''}

Return a JSON object with exactly these fields:
{
  "name": "A descriptive template name",
  "subjectLine": "Compelling subject line (under 60 characters)",
  "previewText": "Preview text that appears next to subject line (under 100 characters)",
  "body": "Full email body with proper paragraphs and formatting. Use line breaks between paragraphs. Make it engaging and persuasive.",
  "ctaText": "Short call-to-action button text (2-4 words)",
  "tags": ["relevant", "tags", "for", "categorization"]
}`;

    const userId = req.user?._id?.toString() || req.user?.id;
    aiJob = createJob('email-templates', req.user?.companyIds?.[0]);
    const result = await generateWithAI(userPrompt, systemPrompt, 2048, undefined, undefined, undefined, undefined, userId);

    // Log raw AI response for debugging (truncated for readability)
    console.log(`[EmailTemplates/AI] Raw response (first 500 chars): ${String(result?.content || '').substring(0, 500)}`);

    // After the generation returns, so a failed call never reports success.
    completeJob(aiJob.jobId, { title: emailType || '' }, 'email-templates');

    res.json({ data: result });
  } catch (error: any) {
    console.error('[EmailTemplates/AI] Generation failed:', error.message);
    if (aiJob) failJob(aiJob.jobId, error?.message || 'Unknown error');
    res.status(500).json({ error: error.message });
  }
});

export default router;