import { Router } from 'express';
import { emailTemplatesService } from './email-templates.service';
import { emailService } from '../../services/email.service';
import { validate } from '../../middleware/validate';
import {
  listEmailTemplatesSchema,
  createEmailTemplateSchema,
  updateEmailTemplateSchema,
  rollbackToVersionSchema,
  validateTemplateSchema,
  sendTestEmailSchema,
} from './email-templates.schemas';
import { logger } from '../../utils/logger';
import { authenticate } from '../../middleware/auth.middleware';
import { requireRole } from '../../middleware/rbac.middleware';
import { UserRole } from '@prisma/client';
import { Request, Response } from 'express';
import { BROADCAST_ROLES } from '../../utils/roles';
import rateLimit from 'express-rate-limit';
import RedisStore from 'rate-limit-redis';
import { redis } from '../../config/redis';
import { seedEmailTemplates } from '../../scripts/seed-email-templates';

const router = Router();

// All email template routes require authentication
router.use(authenticate);

// All routes require broadcast admin role
const requireBroadcastRole = requireRole(...BROADCAST_ROLES);

/**
 * List email templates
 * GET /email-templates
 */
router.get(
  '/',
  requireBroadcastRole,
  validate(listEmailTemplatesSchema, 'query'),
  async (req: Request, res: Response): Promise<void> => {
    try {
      const result = await emailTemplatesService.list(req.query as any);
      res.json(result);
    } catch (error) {
      logger.error('Error listing email templates:', error);
      res.status(500).json({ error: 'Failed to list email templates' });
    }
  },
);

/**
 * Get single email template
 * GET /email-templates/:id
 */
router.get(
  '/:id',
  requireBroadcastRole,
  async (req: Request, res: Response): Promise<void> => {
    try {
      const template = await emailTemplatesService.getById(req.params.id as string);
      res.json(template);
    } catch (error) {
      if (error instanceof Error && error.message === 'Template not found') {
        res.status(404).json({ error: 'Template not found' });
        return;
      }
      logger.error('Error getting email template:', error);
      res.status(500).json({ error: 'Failed to get email template' });
    }
  },
);

/**
 * Create email template
 * POST /email-templates
 */
router.post(
  '/',
  requireBroadcastRole,
  validate(createEmailTemplateSchema),
  async (req: Request, res: Response): Promise<void> => {
    try {
      const template = await emailTemplatesService.create(req.body, req.user!.id);
      res.status(201).json(template);
    } catch (error) {
      if (error instanceof Error && error.message.includes('already exists')) {
        res.status(409).json({ error: error.message });
        return;
      }
      if (error instanceof Error && error.message.includes('validation failed')) {
        res.status(400).json({ error: error.message });
        return;
      }
      logger.error('Error creating email template:', error);
      res.status(500).json({ error: 'Failed to create email template' });
    }
  },
);

/**
 * Update email template
 * PUT /email-templates/:id
 */
router.put(
  '/:id',
  requireBroadcastRole,
  validate(updateEmailTemplateSchema),
  async (req: Request, res: Response): Promise<void> => {
    try {
      const template = await emailTemplatesService.update(req.params.id as string, req.body, req.user!.id);

      // Clear cache so changes take effect immediately
      emailService.clearDatabaseCache(template.key);
      logger.info(`Cleared template cache for: ${template.key}`);

      res.json(template);
    } catch (error) {
      if (error instanceof Error && error.message === 'Template not found') {
        res.status(404).json({ error: 'Template not found' });
        return;
      }
      if (error instanceof Error && error.message.includes('validation failed')) {
        res.status(400).json({ error: error.message });
        return;
      }
      logger.error('Error updating email template:', error);
      res.status(500).json({ error: 'Failed to update email template' });
    }
  },
);

/**
 * Delete email template
 * DELETE /email-templates/:id
 */
router.delete(
  '/:id',
  requireBroadcastRole,
  async (req: Request, res: Response): Promise<void> => {
    try {
      // Fetch template before deleting to get the key
      const template = await emailTemplatesService.getById(req.params.id as string);

      await emailTemplatesService.delete(req.params.id as string);

      // Clear cache for deleted template
      emailService.clearDatabaseCache(template.key);
      logger.info(`Cleared template cache for deleted template: ${template.key}`);

      res.status(204).send();
    } catch (error) {
      if (error instanceof Error && error.message === 'Template not found') {
        res.status(404).json({ error: 'Template not found' });
        return;
      }
      if (error instanceof Error && error.message.includes('Cannot delete system templates')) {
        res.status(403).json({ error: error.message });
        return;
      }
      logger.error('Error deleting email template:', error);
      res.status(500).json({ error: 'Failed to delete email template' });
    }
  },
);

/**
 * Get version history
 * GET /email-templates/:id/versions
 */
router.get(
  '/:id/versions',
  requireBroadcastRole,
  async (req: Request, res: Response): Promise<void> => {
    try {
      const versions = await emailTemplatesService.getVersions(req.params.id as string);
      res.json(versions);
    } catch (error) {
      logger.error('Error getting template versions:', error);
      res.status(500).json({ error: 'Failed to get template versions' });
    }
  },
);

/**
 * Get specific version
 * GET /email-templates/:id/versions/:versionNumber
 */
router.get(
  '/:id/versions/:versionNumber',
  requireBroadcastRole,
  async (req: Request, res: Response): Promise<void> => {
    try {
      const version = await emailTemplatesService.getVersion(
        req.params.id as string,
        parseInt(req.params.versionNumber as string, 10),
      );
      res.json(version);
    } catch (error) {
      if (error instanceof Error && error.message === 'Version not found') {
        res.status(404).json({ error: 'Version not found' });
        return;
      }
      logger.error('Error getting template version:', error);
      res.status(500).json({ error: 'Failed to get template version' });
    }
  },
);

/**
 * Rollback to previous version
 * POST /email-templates/:id/rollback
 */
router.post(
  '/:id/rollback',
  requireBroadcastRole,
  validate(rollbackToVersionSchema),
  async (req: Request, res: Response): Promise<void> => {
    try {
      const template = await emailTemplatesService.rollbackToVersion(
        req.params.id as string,
        req.body,
        req.user!.id,
      );
      res.json(template);
    } catch (error) {
      if (error instanceof Error && (error.message === 'Template not found' || error.message === 'Version not found')) {
        res.status(404).json({ error: error.message });
        return;
      }
      logger.error('Error rolling back template:', error);
      res.status(500).json({ error: 'Failed to rollback template' });
    }
  },
);

/**
 * Validate template syntax
 * POST /email-templates/validate
 */
router.post(
  '/validate',
  requireBroadcastRole,
  validate(validateTemplateSchema),
  async (req: Request, res: Response): Promise<void> => {
    try {
      const result = emailTemplatesService.validateTemplate(req.body);
      res.json(result);
    } catch (error) {
      logger.error('Error validating template:', error);
      res.status(500).json({ error: 'Failed to validate template' });
    }
  },
);

/**
 * Send test email
 * POST /email-templates/:id/test
 * Rate limited to 10 per 15 minutes per user
 */
router.post(
  '/:id/test',
  requireBroadcastRole,
  rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 10,
    standardHeaders: true,
    legacyHeaders: false,
    store: new RedisStore({
      sendCommand: (command: string, ...args: string[]) => redis.call(command, ...args) as Promise<any>,
      prefix: 'rl:email-template-test:',
    }),
    keyGenerator: (req) => req.user!.id,
  }),
  validate(sendTestEmailSchema),
  async (req: Request, res: Response): Promise<void> => {
    try {
      const result = await emailTemplatesService.sendTestEmail(req.params.id as string, req.body, req.user!.id);
      res.json(result);
    } catch (error) {
      if (error instanceof Error && error.message === 'Template not found') {
        res.status(404).json({ error: 'Template not found' });
        return;
      }
      logger.error('Error sending test email:', error);
      res.status(500).json({ error: 'Failed to send test email' });
    }
  },
);

/**
 * Get test logs for template
 * GET /email-templates/:id/test-logs
 */
router.get(
  '/:id/test-logs',
  requireBroadcastRole,
  async (req: Request, res: Response): Promise<void> => {
    try {
      const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 10;
      const logs = await emailTemplatesService.getTestLogs(req.params.id as string, limit);
      res.json(logs);
    } catch (error) {
      logger.error('Error getting test logs:', error);
      res.status(500).json({ error: 'Failed to get test logs' });
    }
  },
);

/**
 * Seed templates from filesystem (SUPER_ADMIN only)
 * POST /email-templates/seed
 */
router.post(
  '/seed',
  requireRole(UserRole.SUPER_ADMIN),
  async (req: Request, res: Response): Promise<void> => {
    try {
      await seedEmailTemplates();
      logger.info('Email templates seeded via API');
      res.json({ success: true, message: 'Templates seeded successfully' });
    } catch (error) {
      logger.error('Error seeding templates:', error);
      res.status(500).json({ error: 'Failed to seed templates' });
    }
  },
);

/**
 * Clear template cache (SUPER_ADMIN only)
 * POST /email-templates/clear-cache
 * Body: { key?: string } - Optional template key to clear. If not provided, clears all.
 */
router.post(
  '/clear-cache',
  requireRole(UserRole.SUPER_ADMIN),
  async (req: Request, res: Response): Promise<void> => {
    try {
      const { key } = req.body;
      emailService.clearDatabaseCache(key);
      logger.info(`Template cache cleared${key ? ` for: ${key}` : ' (all)'}`);
      res.json({ success: true, cleared: key || 'all' });
    } catch (error) {
      logger.error('Error clearing template cache:', error);
      res.status(500).json({ error: 'Failed to clear template cache' });
    }
  },
);

export default router;
