/**
 * ProjectsController - REST Controller for Projects Module
 *
 * Provides endpoints for managing projects, tasks, timesheets,
 * milestones, and team members.
 *
 * @module Projects
 */

import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { AuthMiddleware } from '../../auth/middleware/auth.middleware';
import { AuthService } from '../../auth/services/auth.service';
import { User } from '../../core/entities/user.entity';
import { Tenant } from '../../core/entities/tenant.entity';
import { RefreshToken } from '../../auth/entities/refresh-token.entity';

import {
  ProjectService,
  TaskService,
  TimesheetService,
  MilestoneService,
  ProjectMemberService,
  ProjectStageService,
  ServiceContext,
} from '../services';

import { ProjectStatus } from '../entities/project.entity';
import { TaskStatus, TaskPriority } from '../entities/task.entity';
import { TimesheetStatus } from '../entities/timesheet.entity';

/**
 * Helper to get context from request
 */
const getContext = (req: Request): ServiceContext => {
  if (!req.tenantId) {
    throw new Error('Tenant ID is required');
  }
  return {
    tenantId: req.tenantId,
    userId: req.user?.sub,
  };
};

/**
 * Create projects router
 */
export function createProjectsController(dataSource: DataSource): Router {
  const router = Router();

  // Repositories
  const userRepository = dataSource.getRepository(User);
  const tenantRepository = dataSource.getRepository(Tenant);
  const refreshTokenRepository = dataSource.getRepository(RefreshToken);

  // Services
  const projectService = new ProjectService(dataSource);
  const taskService = new TaskService(dataSource);
  const timesheetService = new TimesheetService(dataSource);
  const milestoneService = new MilestoneService(dataSource);
  const memberService = new ProjectMemberService(dataSource);
  const stageService = new ProjectStageService(dataSource);

  const authService = new AuthService(
    userRepository,
    tenantRepository,
    refreshTokenRepository as any
  );
  const authMiddleware = new AuthMiddleware(authService, dataSource);

  // ========================================
  // PROJECT ROUTES
  // ========================================

  /**
   * GET /projects
   * List all projects
   */
  router.get(
    '/',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const page = parseInt(req.query.page as string) || 1;
        const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);

        const filters = {
          companyId: req.query.companyId as string,
          managerId: req.query.managerId as string,
          partnerId: req.query.partnerId as string,
          status: req.query.status as ProjectStatus,
          search: req.query.search as string,
        };

        const result = await projectService.findAll(ctx, filters, page, limit);

        res.status(200).json({
          success: true,
          data: result.data,
          pagination: {
            total: result.total,
            page: result.page,
            limit: result.limit,
            totalPages: result.totalPages,
          },
        });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * GET /projects/:id
   * Get project by ID
   */
  router.get(
    '/:id',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const project = await projectService.findById(ctx, req.params.id);

        if (!project) {
          res.status(404).json({ error: 'Not Found', message: 'Project not found' });
          return;
        }

        res.status(200).json({ success: true, data: project });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * GET /projects/:id/stats
   * Get project statistics
   */
  router.get(
    '/:id/stats',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const stats = await projectService.getStats(ctx, req.params.id);

        if (!stats) {
          res.status(404).json({ error: 'Not Found', message: 'Project not found' });
          return;
        }

        res.status(200).json({ success: true, data: stats });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * POST /projects
   * Create a new project
   */
  router.post(
    '/',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);

        if (!req.body.companyId || !req.body.name) {
          res.status(400).json({
            error: 'Bad Request',
            message: 'companyId and name are required',
          });
          return;
        }

        const project = await projectService.create(ctx, req.body);
        res.status(201).json({ success: true, data: project });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * PATCH /projects/:id
   * Update a project
   */
  router.patch(
    '/:id',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const project = await projectService.update(ctx, req.params.id, req.body);

        if (!project) {
          res.status(404).json({ error: 'Not Found', message: 'Project not found' });
          return;
        }

        res.status(200).json({ success: true, data: project });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * DELETE /projects/:id
   * Soft delete a project
   */
  router.delete(
    '/:id',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const deleted = await projectService.softDelete(ctx, req.params.id);

        if (!deleted) {
          res.status(404).json({ error: 'Not Found', message: 'Project not found' });
          return;
        }

        res.status(200).json({ success: true, message: 'Project deleted' });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * POST /projects/:id/activate
   * Activate a project
   */
  router.post(
    '/:id/activate',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const project = await projectService.activate(ctx, req.params.id);

        if (!project) {
          res.status(404).json({ error: 'Not Found', message: 'Project not found' });
          return;
        }

        res.status(200).json({ success: true, data: project, message: 'Project activated' });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * POST /projects/:id/complete
   * Complete a project
   */
  router.post(
    '/:id/complete',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const project = await projectService.complete(ctx, req.params.id);

        if (!project) {
          res.status(404).json({ error: 'Not Found', message: 'Project not found' });
          return;
        }

        res.status(200).json({ success: true, data: project, message: 'Project completed' });
      } catch (error) {
        next(error);
      }
    }
  );

  // ========================================
  // TASK ROUTES
  // ========================================

  /**
   * GET /projects/:projectId/tasks
   * List tasks for a project
   */
  router.get(
    '/:projectId/tasks',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const page = parseInt(req.query.page as string) || 1;
        const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);

        const filters = {
          projectId: req.params.projectId,
          stageId: req.query.stageId as string,
          assignedTo: req.query.assignedTo as string,
          status: req.query.status as TaskStatus,
          priority: req.query.priority as TaskPriority,
          search: req.query.search as string,
        };

        const result = await taskService.findAll(ctx, filters, page, limit);

        res.status(200).json({
          success: true,
          data: result.data,
          pagination: {
            total: result.total,
            page: result.page,
            limit: result.limit,
            totalPages: result.totalPages,
          },
        });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * GET /tasks/:id
   * Get task by ID
   */
  router.get(
    '/tasks/:id',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const task = await taskService.findByIdWithHours(ctx, req.params.id);

        if (!task) {
          res.status(404).json({ error: 'Not Found', message: 'Task not found' });
          return;
        }

        res.status(200).json({ success: true, data: task });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * POST /tasks
   * Create a new task
   */
  router.post(
    '/tasks',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);

        if (!req.body.projectId || !req.body.name) {
          res.status(400).json({
            error: 'Bad Request',
            message: 'projectId and name are required',
          });
          return;
        }

        const task = await taskService.create(ctx, req.body);
        res.status(201).json({ success: true, data: task });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * PATCH /tasks/:id
   * Update a task
   */
  router.patch(
    '/tasks/:id',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const task = await taskService.update(ctx, req.params.id, req.body);

        if (!task) {
          res.status(404).json({ error: 'Not Found', message: 'Task not found' });
          return;
        }

        res.status(200).json({ success: true, data: task });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * DELETE /tasks/:id
   * Delete a task
   */
  router.delete(
    '/tasks/:id',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const deleted = await taskService.softDelete(ctx, req.params.id);

        if (!deleted) {
          res.status(404).json({ error: 'Not Found', message: 'Task not found' });
          return;
        }

        res.status(200).json({ success: true, message: 'Task deleted' });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * POST /tasks/:id/move
   * Move task to a different stage
   */
  router.post(
    '/tasks/:id/move',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const { stageId, sequence } = req.body;

        const task = await taskService.move(ctx, req.params.id, stageId, sequence || 0);

        if (!task) {
          res.status(404).json({ error: 'Not Found', message: 'Task not found' });
          return;
        }

        res.status(200).json({ success: true, data: task, message: 'Task moved' });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * POST /tasks/:id/assign
   * Assign task to a user
   */
  router.post(
    '/tasks/:id/assign',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const { userId } = req.body;

        const task = await taskService.assign(ctx, req.params.id, userId);

        if (!task) {
          res.status(404).json({ error: 'Not Found', message: 'Task not found' });
          return;
        }

        res.status(200).json({ success: true, data: task, message: 'Task assigned' });
      } catch (error) {
        next(error);
      }
    }
  );

  // ========================================
  // TIMESHEET ROUTES
  // ========================================

  /**
   * GET /timesheets
   * List all timesheets
   */
  router.get(
    '/timesheets',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const page = parseInt(req.query.page as string) || 1;
        const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);

        const filters = {
          companyId: req.query.companyId as string,
          projectId: req.query.projectId as string,
          taskId: req.query.taskId as string,
          userId: req.query.userId as string,
          status: req.query.status as TimesheetStatus,
          dateFrom: req.query.dateFrom as string,
          dateTo: req.query.dateTo as string,
        };

        const result = await timesheetService.findAll(ctx, filters, page, limit);

        res.status(200).json({
          success: true,
          data: result.data,
          pagination: {
            total: result.total,
            page: result.page,
            limit: result.limit,
            totalPages: result.totalPages,
          },
        });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * GET /timesheets/my
   * Get my timesheets
   */
  router.get(
    '/timesheets/my',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const page = parseInt(req.query.page as string) || 1;
        const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);

        const filters = {
          projectId: req.query.projectId as string,
          dateFrom: req.query.dateFrom as string,
          dateTo: req.query.dateTo as string,
        };

        const result = await timesheetService.findMyTimesheets(ctx, filters, page, limit);

        res.status(200).json({
          success: true,
          data: result.data,
          pagination: {
            total: result.total,
            page: result.page,
            limit: result.limit,
            totalPages: result.totalPages,
          },
        });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * GET /timesheets/pending
   * Get pending approvals
   */
  router.get(
    '/timesheets/pending',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const page = parseInt(req.query.page as string) || 1;
        const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);

        const result = await timesheetService.findPendingApprovals(ctx, {}, page, limit);

        res.status(200).json({
          success: true,
          data: result.data,
          pagination: {
            total: result.total,
            page: result.page,
            limit: result.limit,
            totalPages: result.totalPages,
          },
        });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * POST /timesheets
   * Create a timesheet entry
   */
  router.post(
    '/timesheets',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);

        if (!req.body.companyId || !req.body.projectId || !req.body.date || !req.body.hours) {
          res.status(400).json({
            error: 'Bad Request',
            message: 'companyId, projectId, date and hours are required',
          });
          return;
        }

        const timesheet = await timesheetService.create(ctx, req.body);
        res.status(201).json({ success: true, data: timesheet });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * PATCH /timesheets/:id
   * Update a timesheet
   */
  router.patch(
    '/timesheets/:id',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const timesheet = await timesheetService.update(ctx, req.params.id, req.body);

        if (!timesheet) {
          res.status(404).json({ error: 'Not Found', message: 'Timesheet not found' });
          return;
        }

        res.status(200).json({ success: true, data: timesheet });
      } catch (error) {
        if (error instanceof Error) {
          res.status(400).json({ error: 'Bad Request', message: error.message });
          return;
        }
        next(error);
      }
    }
  );

  /**
   * DELETE /timesheets/:id
   * Delete a timesheet
   */
  router.delete(
    '/timesheets/:id',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const deleted = await timesheetService.delete(ctx, req.params.id);

        if (!deleted) {
          res.status(404).json({ error: 'Not Found', message: 'Timesheet not found' });
          return;
        }

        res.status(200).json({ success: true, message: 'Timesheet deleted' });
      } catch (error) {
        if (error instanceof Error) {
          res.status(400).json({ error: 'Bad Request', message: error.message });
          return;
        }
        next(error);
      }
    }
  );

  /**
   * POST /timesheets/:id/submit
   * Submit timesheet for approval
   */
  router.post(
    '/timesheets/:id/submit',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const timesheet = await timesheetService.submit(ctx, req.params.id);

        if (!timesheet) {
          res.status(404).json({ error: 'Not Found', message: 'Timesheet not found' });
          return;
        }

        res.status(200).json({ success: true, data: timesheet, message: 'Timesheet submitted' });
      } catch (error) {
        if (error instanceof Error) {
          res.status(400).json({ error: 'Bad Request', message: error.message });
          return;
        }
        next(error);
      }
    }
  );

  /**
   * POST /timesheets/:id/approve
   * Approve a timesheet
   */
  router.post(
    '/timesheets/:id/approve',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const timesheet = await timesheetService.approve(ctx, req.params.id);

        if (!timesheet) {
          res.status(404).json({ error: 'Not Found', message: 'Timesheet not found' });
          return;
        }

        res.status(200).json({ success: true, data: timesheet, message: 'Timesheet approved' });
      } catch (error) {
        if (error instanceof Error) {
          res.status(400).json({ error: 'Bad Request', message: error.message });
          return;
        }
        next(error);
      }
    }
  );

  /**
   * POST /timesheets/:id/reject
   * Reject a timesheet
   */
  router.post(
    '/timesheets/:id/reject',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const timesheet = await timesheetService.reject(ctx, req.params.id);

        if (!timesheet) {
          res.status(404).json({ error: 'Not Found', message: 'Timesheet not found' });
          return;
        }

        res.status(200).json({ success: true, data: timesheet, message: 'Timesheet rejected' });
      } catch (error) {
        if (error instanceof Error) {
          res.status(400).json({ error: 'Bad Request', message: error.message });
          return;
        }
        next(error);
      }
    }
  );

  // ========================================
  // MILESTONE ROUTES
  // ========================================

  /**
   * GET /projects/:projectId/milestones
   * List milestones for a project
   */
  router.get(
    '/:projectId/milestones',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const page = parseInt(req.query.page as string) || 1;
        const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);

        const result = await milestoneService.findByProject(
          ctx,
          req.params.projectId,
          page,
          limit
        );

        res.status(200).json({
          success: true,
          data: result.data,
          pagination: {
            total: result.total,
            page: result.page,
            limit: result.limit,
            totalPages: result.totalPages,
          },
        });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * POST /milestones
   * Create a milestone
   */
  router.post(
    '/milestones',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);

        if (!req.body.projectId || !req.body.name) {
          res.status(400).json({
            error: 'Bad Request',
            message: 'projectId and name are required',
          });
          return;
        }

        const milestone = await milestoneService.create(ctx, req.body);
        res.status(201).json({ success: true, data: milestone });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * PATCH /milestones/:id
   * Update a milestone
   */
  router.patch(
    '/milestones/:id',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const milestone = await milestoneService.update(ctx, req.params.id, req.body);

        if (!milestone) {
          res.status(404).json({ error: 'Not Found', message: 'Milestone not found' });
          return;
        }

        res.status(200).json({ success: true, data: milestone });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * DELETE /milestones/:id
   * Delete a milestone
   */
  router.delete(
    '/milestones/:id',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const deleted = await milestoneService.delete(ctx, req.params.id);

        if (!deleted) {
          res.status(404).json({ error: 'Not Found', message: 'Milestone not found' });
          return;
        }

        res.status(200).json({ success: true, message: 'Milestone deleted' });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * POST /milestones/:id/complete
   * Complete a milestone
   */
  router.post(
    '/milestones/:id/complete',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const milestone = await milestoneService.complete(ctx, req.params.id);

        if (!milestone) {
          res.status(404).json({ error: 'Not Found', message: 'Milestone not found' });
          return;
        }

        res.status(200).json({ success: true, data: milestone, message: 'Milestone completed' });
      } catch (error) {
        next(error);
      }
    }
  );

  // ========================================
  // MEMBER ROUTES
  // ========================================

  /**
   * GET /projects/:projectId/members
   * List members of a project
   */
  router.get(
    '/:projectId/members',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const page = parseInt(req.query.page as string) || 1;
        const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);

        const result = await memberService.findByProject(ctx, req.params.projectId, page, limit);

        res.status(200).json({
          success: true,
          data: result.data,
          pagination: {
            total: result.total,
            page: result.page,
            limit: result.limit,
            totalPages: result.totalPages,
          },
        });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * POST /projects/:projectId/members
   * Add member to a project
   */
  router.post(
    '/:projectId/members',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);

        if (!req.body.userId) {
          res.status(400).json({
            error: 'Bad Request',
            message: 'userId is required',
          });
          return;
        }

        const member = await memberService.addMember(ctx, {
          projectId: req.params.projectId,
          userId: req.body.userId,
          role: req.body.role,
        });

        res.status(201).json({ success: true, data: member });
      } catch (error) {
        if (error instanceof Error) {
          res.status(400).json({ error: 'Bad Request', message: error.message });
          return;
        }
        next(error);
      }
    }
  );

  /**
   * DELETE /projects/:projectId/members/:userId
   * Remove member from a project
   */
  router.delete(
    '/:projectId/members/:userId',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const deleted = await memberService.removeMemberByProjectAndUser(
          ctx,
          req.params.projectId,
          req.params.userId
        );

        if (!deleted) {
          res.status(404).json({ error: 'Not Found', message: 'Member not found' });
          return;
        }

        res.status(200).json({ success: true, message: 'Member removed' });
      } catch (error) {
        next(error);
      }
    }
  );

  // ========================================
  // STAGE ROUTES
  // ========================================

  /**
   * GET /stages
   * List global stages
   */
  router.get(
    '/stages',
    authMiddleware.authenticate,
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const projectId = req.query.projectId as string | undefined;

        const result = projectId
          ? await stageService.findByProject(ctx, projectId)
          : await stageService.findGlobalStages(ctx);

        res.status(200).json({
          success: true,
          data: result.data,
          pagination: {
            total: result.total,
            page: result.page,
            limit: result.limit,
            totalPages: result.totalPages,
          },
        });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * POST /stages
   * Create a stage
   */
  router.post(
    '/stages',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);

        if (!req.body.name) {
          res.status(400).json({
            error: 'Bad Request',
            message: 'name is required',
          });
          return;
        }

        const stage = await stageService.create(ctx, req.body);
        res.status(201).json({ success: true, data: stage });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * PATCH /stages/:id
   * Update a stage
   */
  router.patch(
    '/stages/:id',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'manager', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const stage = await stageService.update(ctx, req.params.id, req.body);

        if (!stage) {
          res.status(404).json({ error: 'Not Found', message: 'Stage not found' });
          return;
        }

        res.status(200).json({ success: true, data: stage });
      } catch (error) {
        next(error);
      }
    }
  );

  /**
   * DELETE /stages/:id
   * Delete a stage
   */
  router.delete(
    '/stages/:id',
    authMiddleware.authenticate,
    authMiddleware.authorize('admin', 'director'),
    async (req: Request, res: Response, next: NextFunction): Promise<void> => {
      try {
        const ctx = getContext(req);
        const deleted = await stageService.delete(ctx, req.params.id);

        if (!deleted) {
          res.status(404).json({ error: 'Not Found', message: 'Stage not found' });
          return;
        }

        res.status(200).json({ success: true, message: 'Stage deleted' });
      } catch (error) {
        next(error);
      }
    }
  );

  return router;
}

export default createProjectsController;
