/**
 * Workflow Template Routes — Super Admin CRUD
 *
 * Super Admin operations are gated by requireRole('super-admin').
 * Mounted at: /api/super-admin/workflow-templates
 *
 * IMPORTANT: Literal routes (e.g. /seed) must come BEFORE parameterized routes (e.g. /:id)
 * so Express doesn't match "seed" as an :id parameter.
 */

import { Router, Request, Response } from 'express';
import { getModels } from '../models';
import { requireRole } from '../middleware/auth';
import { authenticateJwtOrApiToken } from '../middleware/dualAuth';

const router = Router();

// ============================================
// HELPER: Validate workflow template input
// ============================================

function validateTemplateInput(data: any): string | null {
  if (!data.name || typeof data.name !== 'string' || data.name.trim().length < 2) {
    return 'Template name is required (min 2 characters)';
  }
  if (!data.description || typeof data.description !== 'string' || data.description.trim().length < 5) {
    return 'Template description is required (min 5 characters)';
  }
  if (!data.steps || !Array.isArray(data.steps) || data.steps.length === 0) {
    return 'At least one workflow step is required';
  }
  for (let i = 0; i < data.steps.length; i++) {
    const step = data.steps[i];
    if (!step.title || !step.title.trim()) return `Step ${i + 1}: title is required`;
    if (!step.route || !step.route.trim()) return `Step ${i + 1}: route is required`;
    if (!step.actions || !Array.isArray(step.actions) || step.actions.length === 0) {
      return `Step ${i + 1}: at least one action is required`;
    }
    for (let j = 0; j < step.actions.length; j++) {
      const action = step.actions[j];
      if (!action.label || !action.label.trim()) return `Step ${i + 1}, Action ${j + 1}: label is required`;
      if (!action.route || !action.route.trim()) return `Step ${i + 1}, Action ${j + 1}: route is required`;
      if (!action.completionKey || !action.completionKey.trim()) return `Step ${i + 1}, Action ${j + 1}: completionKey is required`;
    }
  }
  return null;
}

// ============================================
// SUPER ADMIN ROUTES
// ============================================

// All super-admin routes require authentication + super-admin role
router.use(authenticateJwtOrApiToken);
router.use(requireRole('super-admin'));

// --- List all templates (with filters) ---
router.get('/', async (req: Request, res: Response) => {
  try {
    const { WorkflowTemplate } = getModels();
    const { status, search } = req.query;
    const filter: any = {};
    if (status) filter.status = status;
    if (search) {
      filter.$or = [
        { name: { $regex: search, $options: 'i' } },
        { description: { $regex: search, $options: 'i' } },
      ];
    }
    // Include soft-deleted if explicitly requested
    if (req.query.includeDeleted !== 'true') {
      filter.deletedAt = null;
    }
    const templates = await WorkflowTemplate.find(filter).sort({ displayOrder: 1, createdAt: -1 }).lean();
    res.json(templates);
  } catch (error: any) {
    console.error('[SuperAdmin] List workflow templates error:', error.message);
    res.status(500).json({ error: 'Failed to fetch workflow templates' });
  }
});

// --- Create template ---
router.post('/', async (req: Request, res: Response) => {
  try {
    const { WorkflowTemplate } = getModels();
    const data = req.body;
    const validationError = validateTemplateInput(data);
    if (validationError) {
      res.status(400).json({ error: validationError });
      return;
    }
    // Generate slug from name
    const slug = data.slug || data.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
    // Check slug uniqueness
    const existing = await WorkflowTemplate.findOne({ slug }).lean();
    if (existing) {
      res.status(409).json({ error: 'A template with this slug already exists' });
      return;
    }
    // Normalize step orders and action orders
    const steps = (data.steps || []).map((step: any, index: number) => ({
      ...step,
      stepOrder: step.stepOrder ?? index + 1,
      actions: (step.actions || []).map((action: any, actionIndex: number) => ({
        ...action,
        actionOrder: action.actionOrder ?? actionIndex + 1,
      })),
    }));
    const template = await WorkflowTemplate.create({
      name: data.name.trim(),
      slug,
      description: data.description.trim(),
      status: data.status || 'draft',
      displayOrder: data.displayOrder ?? 0,
      icon: data.icon || 'Rocket',
      category: data.category || '',
      targetAudience: data.targetAudience || '',
      startDate: data.startDate || undefined,
      endDate: data.endDate || undefined,
      version: 1,
      createdById: (req as any).user?._id?.toString(),
      steps,
    });
    res.status(201).json(template);
  } catch (error: any) {
    if (error.code === 11000) {
      res.status(409).json({ error: 'A template with this slug already exists' });
      return;
    }
    console.error('[SuperAdmin] Create workflow template error:', error.message);
    res.status(500).json({ error: 'Failed to create workflow template' });
  }
});

// --- Seed default template (MUST come before /:id routes) ---
router.post('/seed', async (req: Request, res: Response) => {
  try {
    const { seedWorkflowTemplates } = await import('../utils/seedWorkflowTemplates');
    await seedWorkflowTemplates();
    res.json({ message: 'Default workflow template seeded successfully' });
  } catch (error: any) {
    console.error('[SuperAdmin] Seed workflow templates error:', error.message);
    res.status(500).json({ error: 'Failed to seed workflow templates' });
  }
});

// --- Get single template ---
router.get('/:id', async (req: Request, res: Response) => {
  try {
    const { WorkflowTemplate } = getModels();
    const template = await WorkflowTemplate.findById(req.params.id).lean();
    if (!template) {
      res.status(404).json({ error: 'Workflow template not found' });
      return;
    }
    res.json(template);
  } catch (error: any) {
    console.error('[SuperAdmin] Get workflow template error:', error.message);
    res.status(500).json({ error: 'Failed to fetch workflow template' });
  }
});

// --- Update template ---
router.put('/:id', async (req: Request, res: Response) => {
  try {
    const { WorkflowTemplate } = getModels();
    const data = req.body;
    const existing = await WorkflowTemplate.findById(req.params.id).lean();
    if (!existing) {
      res.status(404).json({ error: 'Workflow template not found' });
      return;
    }
    // Prevent editing archived templates (only status change is allowed)
    if (existing.status === 'archived' && data.status !== 'archived') {
      res.status(400).json({ error: 'Archived templates cannot be edited. Change status first.' });
      return;
    }
    const update: any = {};
    if (data.name !== undefined) update.name = data.name.trim();
    if (data.description !== undefined) update.description = data.description.trim();
    if (data.status !== undefined) update.status = data.status;
    if (data.displayOrder !== undefined) update.displayOrder = data.displayOrder;
    if (data.icon !== undefined) update.icon = data.icon;
    if (data.category !== undefined) update.category = data.category;
    if (data.targetAudience !== undefined) update.targetAudience = data.targetAudience;
    if (data.startDate !== undefined) update.startDate = data.startDate;
    if (data.endDate !== undefined) update.endDate = data.endDate;
    if (data.steps !== undefined) {
      update.steps = data.steps.map((step: any, index: number) => ({
        ...step,
        stepOrder: step.stepOrder ?? index + 1,
        actions: (step.actions || []).map((action: any, actionIndex: number) => ({
          ...action,
          actionOrder: action.actionOrder ?? actionIndex + 1,
        })),
      }));
      update.version = (existing.version || 1) + 1;
    }
    const updated = await WorkflowTemplate.findByIdAndUpdate(
      req.params.id,
      { $set: update },
      { new: true, runValidators: true }
    ).lean();
    res.json(updated);
  } catch (error: any) {
    console.error('[SuperAdmin] Update workflow template error:', error.message);
    res.status(500).json({ error: 'Failed to update workflow template' });
  }
});

// --- Update template status (activate/deactivate/archive) ---
router.put('/:id/status', async (req: Request, res: Response) => {
  try {
    const { WorkflowTemplate } = getModels();
    const { status } = req.body;
    if (!['draft', 'active', 'inactive', 'archived'].includes(status)) {
      res.status(400).json({ error: 'Invalid status. Must be draft, active, inactive, or archived' });
      return;
    }
    // Validate that active templates have at least one step
    if (status === 'active') {
      const template = await WorkflowTemplate.findById(req.params.id).lean();
      if (!template) {
        res.status(404).json({ error: 'Workflow template not found' });
        return;
      }
      if (!template.steps || template.steps.length === 0) {
        res.status(400).json({ error: 'Active templates must have at least one step' });
        return;
      }
    }
    const updated = await WorkflowTemplate.findByIdAndUpdate(
      req.params.id,
      { $set: { status } },
      { new: true, runValidators: true }
    ).lean();
    if (!updated) {
      res.status(404).json({ error: 'Workflow template not found' });
      return;
    }
    res.json(updated);
  } catch (error: any) {
    console.error('[SuperAdmin] Update workflow template status error:', error.message);
    res.status(500).json({ error: 'Failed to update template status' });
  }
});

// --- Reorder steps ---
router.put('/:id/reorder-steps', async (req: Request, res: Response) => {
  try {
    const { WorkflowTemplate } = getModels();
    const { steps: stepOrders } = req.body;
    if (!Array.isArray(stepOrders)) {
      res.status(400).json({ error: 'steps must be an array' });
      return;
    }
    const template = await WorkflowTemplate.findById(req.params.id).lean();
    if (!template) {
      res.status(404).json({ error: 'Workflow template not found' });
      return;
    }
    // Reorder existing steps
    const reorderedSteps = stepOrders.map((order: any, index: number) => {
      const existingStep = template.steps.find((s: any) => s.stepKey === order.stepKey);
      if (!existingStep) return null;
      return { ...existingStep.toObject(), stepOrder: index + 1 };
    }).filter(Boolean);
    const updated = await WorkflowTemplate.findByIdAndUpdate(
      req.params.id,
      { $set: { steps: reorderedSteps, version: (template.version || 1) + 1 } },
      { new: true, runValidators: true }
    ).lean();
    res.json(updated);
  } catch (error: any) {
    console.error('[SuperAdmin] Reorder workflow template steps error:', error.message);
    res.status(500).json({ error: 'Failed to reorder steps' });
  }
});

// --- Duplicate template ---
router.post('/:id/duplicate', async (req: Request, res: Response) => {
  try {
    const { WorkflowTemplate } = getModels();
    const original = await WorkflowTemplate.findById(req.params.id).lean();
    if (!original) {
      res.status(404).json({ error: 'Workflow template not found' });
      return;
    }
    const slug = `${original.slug}-copy`;
    // Check slug uniqueness
    const existingCopy = await WorkflowTemplate.findOne({ slug }).lean();
    const finalSlug = existingCopy ? `${slug}-${Date.now()}` : slug;
    const duplicate = await WorkflowTemplate.create({
      name: `${original.name} (Copy)`,
      slug: finalSlug,
      description: original.description,
      status: 'draft', // Copies start as draft
      displayOrder: original.displayOrder + 1,
      icon: original.icon,
      category: original.category,
      targetAudience: original.targetAudience,
      steps: original.steps.map((step: any) => ({
        ...step,
        _id: undefined, // Let MongoDB generate new IDs
        actions: step.actions.map((action: any) => ({
          ...action,
          _id: undefined,
        })),
      })),
      version: 1,
      createdById: (req as any).user?._id?.toString(),
    });
    res.status(201).json(duplicate);
  } catch (error: any) {
    console.error('[SuperAdmin] Duplicate workflow template error:', error.message);
    res.status(500).json({ error: 'Failed to duplicate workflow template' });
  }
});

// --- Soft-delete template ---
router.delete('/:id', async (req: Request, res: Response) => {
  try {
    const { WorkflowTemplate } = getModels();
    const template = await WorkflowTemplate.findById(req.params.id).lean();
    if (!template) {
      res.status(404).json({ error: 'Workflow template not found' });
      return;
    }
    // Soft delete by setting deletedAt
    await WorkflowTemplate.findByIdAndUpdate(req.params.id, {
      $set: { deletedAt: new Date(), status: 'archived' },
    });
    res.json({ message: 'Workflow template deleted', id: req.params.id });
  } catch (error: any) {
    console.error('[SuperAdmin] Delete workflow template error:', error.message);
    res.status(500).json({ error: 'Failed to delete workflow template' });
  }
});

export default router;