import { Router } from 'express';
import { z } from 'zod';
import { WorkflowController } from '../controllers/workflow.controller';
import { validate, validateMultiple } from '../middleware/validation.middleware';
import { generalLimiter, strictLimiter } from '../middleware/rateLimit.middleware';

const router = Router();
const workflowController = new WorkflowController();

// Validation schemas
const TransitionSchema = z.object({
  taskId: z.string().uuid(),
  event: z.string(),
  metadata: z.record(z.string(), z.any()).optional(),
  userId: z.string().uuid().optional(),
  reason: z.string().optional()
});

const WebhookConfigSchema = z.object({
  url: z.string().url(),
  events: z.array(z.string()),
  headers: z.record(z.string(), z.string()).optional(),
  secret: z.string().optional(),
  active: z.boolean().default(true),
  retryConfig: z.object({
    maxRetries: z.number().int().min(0).max(10).default(3),
    retryDelay: z.number().int().min(1000).default(2000),
    backoffMultiplier: z.number().min(1).max(5).default(2)
  }).optional()
});

const JobSchema = z.object({
  type: z.string(),
  taskId: z.string().uuid().optional(),
  payload: z.any(),
  metadata: z.record(z.string(), z.any()).optional(),
  priority: z.number().int().min(1).max(20).optional(),
  delay: z.number().int().min(0).optional(),
  cron: z.string().optional()
});

const AuditQuerySchema = z.object({
  entityType: z.string().optional(),
  entityId: z.string().optional(),
  actorId: z.string().optional(),
  action: z.string().optional(),
  severity: z.enum(['info', 'warning', 'error', 'critical']).optional(),
  startDate: z.string().datetime().optional(),
  endDate: z.string().datetime().optional(),
  tags: z.array(z.string()).optional(),
  limit: z.coerce.number().int().min(1).max(1000).default(100),
  offset: z.coerce.number().int().min(0).default(0),
  sort: z.string().optional()
});

/**
 * State Machine Routes
 */

// Get current state for a task
router.get(
  '/state/:taskId',
  generalLimiter,
  validate(z.object({ taskId: z.string().uuid() }), 'params'),
  (req: any, res) => workflowController.getTaskState(req, res)
);

// Get available transitions for a task
router.get(
  '/state/:taskId/transitions',
  generalLimiter,
  validate(z.object({ taskId: z.string().uuid() }), 'params'),
  (req: any, res) => workflowController.getAvailableTransitions(req, res)
);

// Execute a state transition
router.post(
  '/state/transition',
  strictLimiter,
  validate(TransitionSchema, 'body'),
  (req: any, res) => workflowController.executeTransition(req, res)
);

// Validate if a transition is allowed
router.post(
  '/state/validate',
  generalLimiter,
  validate(TransitionSchema, 'body'),
  (req: any, res) => workflowController.validateTransition(req, res)
);

/**
 * Webhook Routes
 */

// Get all webhooks
router.get(
  '/webhooks',
  generalLimiter,
  validate(z.object({
    active: z.coerce.boolean().optional(),
    event: z.string().optional()
  }), 'query'),
  (req: any, res) => workflowController.getWebhooks(req, res)
);

// Register a new webhook
router.post(
  '/webhooks',
  strictLimiter,
  validate(WebhookConfigSchema, 'body'),
  (req: any, res) => workflowController.registerWebhook(req, res)
);

// Update webhook configuration
router.put(
  '/webhooks/:id',
  strictLimiter,
  validateMultiple({
    params: z.object({ id: z.string().uuid() }),
    body: WebhookConfigSchema.partial()
  }),
  (req: any, res) => workflowController.updateWebhook(req, res)
);

// Delete a webhook
router.delete(
  '/webhooks/:id',
  strictLimiter,
  validate(z.object({ id: z.string().uuid() }), 'params'),
  (req: any, res) => workflowController.deleteWebhook(req, res)
);

// Test webhook endpoint
router.post(
  '/webhooks/:id/test',
  strictLimiter,
  validate(z.object({ id: z.string().uuid() }), 'params'),
  (req: any, res) => workflowController.testWebhook(req, res)
);

// Get webhook delivery history
router.get(
  '/webhooks/:id/deliveries',
  generalLimiter,
  validateMultiple({
    params: z.object({ id: z.string().uuid() }),
    query: z.object({ limit: z.coerce.number().int().min(1).max(100).default(100) })
  }),
  (req: any, res) => workflowController.getWebhookDeliveries(req, res)
);

/**
 * Audit Log Routes
 */

// Query audit logs
router.get(
  '/audit',
  generalLimiter,
  validate(AuditQuerySchema, 'query'),
  (req: any, res) => workflowController.queryAuditLogs(req, res)
);

// Get audit statistics
router.get(
  '/audit/statistics',
  generalLimiter,
  validate(z.object({
    startDate: z.string().datetime().optional(),
    endDate: z.string().datetime().optional()
  }), 'query'),
  (req: any, res) => workflowController.getAuditStatistics(req, res)
);

// Get audit timeline for an entity
router.get(
  '/audit/timeline/:entityId',
  generalLimiter,
  validateMultiple({
    params: z.object({ entityId: z.string() }),
    query: z.object({ entityType: z.string().optional() })
  }),
  (req: any, res) => workflowController.getAuditTimeline(req, res)
);

// Export audit logs
router.get(
  '/audit/export',
  strictLimiter,
  validate(AuditQuerySchema.extend({
    format: z.enum(['json', 'csv']).default('json')
  }), 'query'),
  (req: any, res) => workflowController.exportAuditLogs(req, res)
);

/**
 * Job Queue Routes
 */

// Add a job to queue
router.post(
  '/jobs',
  strictLimiter,
  validate(JobSchema.extend({
    queue: z.string().default('workflow')
  }), 'body'),
  (req: any, res) => workflowController.addJob(req, res)
);

// Schedule a job
router.post(
  '/jobs/schedule',
  strictLimiter,
  validate(JobSchema.extend({
    queue: z.string().default('scheduled'),
    delay: z.number().int().min(0).optional(),
    scheduleAt: z.string().datetime().optional()
  }), 'body'),
  (req: any, res) => workflowController.scheduleJob(req, res)
);

// Add recurring job
router.post(
  '/jobs/recurring',
  strictLimiter,
  validate(JobSchema.extend({
    queue: z.string().default('scheduled'),
    cron: z.string()
  }), 'body'),
  (req: any, res) => workflowController.addRecurringJob(req, res)
);

// Get queue statistics
router.get(
  '/jobs/queues/:name/stats',
  generalLimiter,
  validate(z.object({ name: z.string() }), 'params'),
  (req: any, res) => workflowController.getQueueStatistics(req, res)
);

// Pause a queue
router.post(
  '/jobs/queues/:name/pause',
  strictLimiter,
  validate(z.object({ name: z.string() }), 'params'),
  (req: any, res) => workflowController.pauseQueue(req, res)
);

// Resume a queue
router.post(
  '/jobs/queues/:name/resume',
  strictLimiter,
  validate(z.object({ name: z.string() }), 'params'),
  (req: any, res) => workflowController.resumeQueue(req, res)
);

// Clear a queue
router.delete(
  '/jobs/queues/:name/clear',
  strictLimiter,
  validate(z.object({ name: z.string() }), 'params'),
  (req: any, res) => workflowController.clearQueue(req, res)
);

/**
 * Git Integration Routes
 */

// Create branch for task
router.post(
  '/git/branch',
  strictLimiter,
  validate(z.object({
    taskId: z.string().uuid(),
    taskTitle: z.string()
  }), 'body'),
  (req: any, res) => workflowController.createTaskBranch(req, res)
);

// Get Git info for task
router.get(
  '/git/task/:taskId',
  generalLimiter,
  validate(z.object({ taskId: z.string().uuid() }), 'params'),
  (req: any, res) => workflowController.getTaskGitInfo(req, res)
);

// Handle GitHub webhook events
router.post(
  '/git/webhook',
  strictLimiter,
  (req: any, res) => workflowController.handleGitWebhook(req, res)
);

export default router;