import { Response, NextFunction } from 'express';
import { z } from 'zod';
import { employeesService, CreateEmployeeDto, UpdateEmployeeDto, EmployeeFilters } from './employees.service.js';
import { departmentsService, CreateDepartmentDto, UpdateDepartmentDto, DepartmentFilters, CreateJobPositionDto, UpdateJobPositionDto } from './departments.service.js';
import { contractsService, CreateContractDto, UpdateContractDto, ContractFilters } from './contracts.service.js';
import { leavesService, CreateLeaveDto, UpdateLeaveDto, LeaveFilters, CreateLeaveTypeDto, UpdateLeaveTypeDto } from './leaves.service.js';
import { AuthenticatedRequest } from '../../shared/middleware/auth.middleware.js';
import { ValidationError } from '../../shared/errors/index.js';

// Employee schemas
const createEmployeeSchema = z.object({
  company_id: z.string().uuid(),
  employee_number: z.string().min(1).max(50),
  first_name: z.string().min(1).max(100),
  last_name: z.string().min(1).max(100),
  middle_name: z.string().max(100).optional(),
  user_id: z.string().uuid().optional(),
  birth_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
  gender: z.string().max(20).optional(),
  marital_status: z.string().max(20).optional(),
  nationality: z.string().max(100).optional(),
  identification_id: z.string().max(50).optional(),
  identification_type: z.string().max(50).optional(),
  social_security_number: z.string().max(50).optional(),
  tax_id: z.string().max(50).optional(),
  email: z.string().email().max(255).optional(),
  work_email: z.string().email().max(255).optional(),
  phone: z.string().max(50).optional(),
  work_phone: z.string().max(50).optional(),
  mobile: z.string().max(50).optional(),
  emergency_contact: z.string().max(255).optional(),
  emergency_phone: z.string().max(50).optional(),
  street: z.string().max(255).optional(),
  city: z.string().max(100).optional(),
  state: z.string().max(100).optional(),
  zip: z.string().max(20).optional(),
  country: z.string().max(100).optional(),
  department_id: z.string().uuid().optional(),
  job_position_id: z.string().uuid().optional(),
  manager_id: z.string().uuid().optional(),
  hire_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
  bank_name: z.string().max(100).optional(),
  bank_account: z.string().max(50).optional(),
  bank_clabe: z.string().max(20).optional(),
  photo_url: z.string().url().max(500).optional(),
  notes: z.string().optional(),
});

const updateEmployeeSchema = createEmployeeSchema.partial().omit({ company_id: true, employee_number: true, hire_date: true });

const employeeQuerySchema = z.object({
  company_id: z.string().uuid().optional(),
  department_id: z.string().uuid().optional(),
  status: z.enum(['active', 'inactive', 'on_leave', 'terminated']).optional(),
  manager_id: z.string().uuid().optional(),
  search: z.string().optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().positive().max(100).default(20),
});

// Department schemas
const createDepartmentSchema = z.object({
  company_id: z.string().uuid(),
  name: z.string().min(1).max(100),
  code: z.string().max(20).optional(),
  parent_id: z.string().uuid().optional(),
  manager_id: z.string().uuid().optional(),
  description: z.string().optional(),
  color: z.string().max(20).optional(),
});

const updateDepartmentSchema = z.object({
  name: z.string().min(1).max(100).optional(),
  code: z.string().max(20).optional().nullable(),
  parent_id: z.string().uuid().optional().nullable(),
  manager_id: z.string().uuid().optional().nullable(),
  description: z.string().optional().nullable(),
  color: z.string().max(20).optional().nullable(),
  active: z.boolean().optional(),
});

const departmentQuerySchema = z.object({
  company_id: z.string().uuid().optional(),
  active: z.coerce.boolean().optional(),
  search: z.string().optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().positive().max(100).default(50),
});

// Job Position schemas
const createJobPositionSchema = z.object({
  name: z.string().min(1).max(100),
  department_id: z.string().uuid().optional(),
  description: z.string().optional(),
  requirements: z.string().optional(),
  responsibilities: z.string().optional(),
  min_salary: z.number().min(0).optional(),
  max_salary: z.number().min(0).optional(),
});

const updateJobPositionSchema = z.object({
  name: z.string().min(1).max(100).optional(),
  department_id: z.string().uuid().optional().nullable(),
  description: z.string().optional().nullable(),
  requirements: z.string().optional().nullable(),
  responsibilities: z.string().optional().nullable(),
  min_salary: z.number().min(0).optional().nullable(),
  max_salary: z.number().min(0).optional().nullable(),
  active: z.boolean().optional(),
});

// Contract schemas
const createContractSchema = z.object({
  company_id: z.string().uuid(),
  employee_id: z.string().uuid(),
  name: z.string().min(1).max(100),
  reference: z.string().max(100).optional(),
  contract_type: z.enum(['permanent', 'temporary', 'contractor', 'internship', 'part_time']),
  job_position_id: z.string().uuid().optional(),
  department_id: z.string().uuid().optional(),
  date_start: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
  date_end: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
  trial_date_end: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
  wage: z.number().min(0),
  wage_type: z.string().max(20).optional(),
  currency_id: z.string().uuid().optional(),
  hours_per_week: z.number().min(0).max(168).optional(),
  vacation_days: z.number().int().min(0).optional(),
  christmas_bonus_days: z.number().int().min(0).optional(),
  document_url: z.string().url().max(500).optional(),
  notes: z.string().optional(),
});

const updateContractSchema = z.object({
  reference: z.string().max(100).optional().nullable(),
  job_position_id: z.string().uuid().optional().nullable(),
  department_id: z.string().uuid().optional().nullable(),
  date_end: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional().nullable(),
  trial_date_end: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional().nullable(),
  wage: z.number().min(0).optional(),
  wage_type: z.string().max(20).optional(),
  currency_id: z.string().uuid().optional().nullable(),
  hours_per_week: z.number().min(0).max(168).optional(),
  vacation_days: z.number().int().min(0).optional(),
  christmas_bonus_days: z.number().int().min(0).optional(),
  document_url: z.string().url().max(500).optional().nullable(),
  notes: z.string().optional().nullable(),
});

const contractQuerySchema = z.object({
  company_id: z.string().uuid().optional(),
  employee_id: z.string().uuid().optional(),
  status: z.enum(['draft', 'active', 'expired', 'terminated', 'cancelled']).optional(),
  contract_type: z.enum(['permanent', 'temporary', 'contractor', 'internship', 'part_time']).optional(),
  search: z.string().optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().positive().max(100).default(20),
});

// Leave Type schemas
const createLeaveTypeSchema = z.object({
  name: z.string().min(1).max(100),
  code: z.string().max(20).optional(),
  leave_type: z.enum(['vacation', 'sick', 'personal', 'maternity', 'paternity', 'bereavement', 'unpaid', 'other']),
  requires_approval: z.boolean().optional(),
  max_days: z.number().int().min(1).optional(),
  is_paid: z.boolean().optional(),
  color: z.string().max(20).optional(),
});

const updateLeaveTypeSchema = z.object({
  name: z.string().min(1).max(100).optional(),
  code: z.string().max(20).optional().nullable(),
  requires_approval: z.boolean().optional(),
  max_days: z.number().int().min(1).optional().nullable(),
  is_paid: z.boolean().optional(),
  color: z.string().max(20).optional().nullable(),
  active: z.boolean().optional(),
});

// Leave schemas
const createLeaveSchema = z.object({
  company_id: z.string().uuid(),
  employee_id: z.string().uuid(),
  leave_type_id: z.string().uuid(),
  name: z.string().max(255).optional(),
  date_from: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
  date_to: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
  description: z.string().optional(),
});

const updateLeaveSchema = z.object({
  leave_type_id: z.string().uuid().optional(),
  name: z.string().max(255).optional().nullable(),
  date_from: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
  date_to: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
  description: z.string().optional().nullable(),
});

const leaveQuerySchema = z.object({
  company_id: z.string().uuid().optional(),
  employee_id: z.string().uuid().optional(),
  leave_type_id: z.string().uuid().optional(),
  status: z.enum(['draft', 'submitted', 'approved', 'rejected', 'cancelled']).optional(),
  date_from: z.string().optional(),
  date_to: z.string().optional(),
  search: z.string().optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().positive().max(100).default(20),
});

const terminateSchema = z.object({
  termination_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
});

const rejectSchema = z.object({
  reason: z.string().min(1),
});

class HrController {
  // ========== EMPLOYEES ==========

  async getEmployees(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const queryResult = employeeQuerySchema.safeParse(req.query);
      if (!queryResult.success) {
        throw new ValidationError('Parametros de consulta invalidos', queryResult.error.errors);
      }

      const filters: EmployeeFilters = queryResult.data;
      const result = await employeesService.findAll(req.tenantId!, filters);

      res.json({
        success: true,
        data: result.data,
        meta: { total: result.total, page: filters.page, limit: filters.limit, totalPages: Math.ceil(result.total / (filters.limit || 20)) },
      });
    } catch (error) {
      next(error);
    }
  }

  async getEmployee(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const employee = await employeesService.findById(req.params.id, req.tenantId!);
      res.json({ success: true, data: employee });
    } catch (error) {
      next(error);
    }
  }

  async createEmployee(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = createEmployeeSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de empleado invalidos', parseResult.error.errors);
      }

      const dto: CreateEmployeeDto = parseResult.data;
      const employee = await employeesService.create(dto, req.tenantId!, req.user!.userId);

      res.status(201).json({ success: true, data: employee, message: 'Empleado creado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async updateEmployee(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = updateEmployeeSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de empleado invalidos', parseResult.error.errors);
      }

      const dto: UpdateEmployeeDto = parseResult.data;
      const employee = await employeesService.update(req.params.id, dto, req.tenantId!, req.user!.userId);

      res.json({ success: true, data: employee, message: 'Empleado actualizado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async terminateEmployee(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = terminateSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos invalidos', parseResult.error.errors);
      }

      const employee = await employeesService.terminate(req.params.id, parseResult.data.termination_date, req.tenantId!, req.user!.userId);
      res.json({ success: true, data: employee, message: 'Empleado dado de baja exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async reactivateEmployee(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const employee = await employeesService.reactivate(req.params.id, req.tenantId!, req.user!.userId);
      res.json({ success: true, data: employee, message: 'Empleado reactivado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async deleteEmployee(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await employeesService.delete(req.params.id, req.tenantId!);
      res.json({ success: true, message: 'Empleado eliminado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async getSubordinates(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const subordinates = await employeesService.getSubordinates(req.params.id, req.tenantId!);
      res.json({ success: true, data: subordinates });
    } catch (error) {
      next(error);
    }
  }

  // ========== DEPARTMENTS ==========

  async getDepartments(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const queryResult = departmentQuerySchema.safeParse(req.query);
      if (!queryResult.success) {
        throw new ValidationError('Parametros de consulta invalidos', queryResult.error.errors);
      }

      const filters: DepartmentFilters = queryResult.data;
      const result = await departmentsService.findAll(req.tenantId!, filters);

      res.json({
        success: true,
        data: result.data,
        meta: { total: result.total, page: filters.page, limit: filters.limit, totalPages: Math.ceil(result.total / (filters.limit || 50)) },
      });
    } catch (error) {
      next(error);
    }
  }

  async getDepartment(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const department = await departmentsService.findById(req.params.id, req.tenantId!);
      res.json({ success: true, data: department });
    } catch (error) {
      next(error);
    }
  }

  async createDepartment(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = createDepartmentSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de departamento invalidos', parseResult.error.errors);
      }

      const dto: CreateDepartmentDto = parseResult.data;
      const department = await departmentsService.create(dto, req.tenantId!, req.user!.userId);

      res.status(201).json({ success: true, data: department, message: 'Departamento creado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async updateDepartment(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = updateDepartmentSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de departamento invalidos', parseResult.error.errors);
      }

      const dto: UpdateDepartmentDto = parseResult.data;
      const department = await departmentsService.update(req.params.id, dto, req.tenantId!);

      res.json({ success: true, data: department, message: 'Departamento actualizado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async deleteDepartment(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await departmentsService.delete(req.params.id, req.tenantId!);
      res.json({ success: true, message: 'Departamento eliminado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  // ========== JOB POSITIONS ==========

  async getJobPositions(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const includeInactive = req.query.include_inactive === 'true';
      const positions = await departmentsService.getJobPositions(req.tenantId!, includeInactive);
      res.json({ success: true, data: positions });
    } catch (error) {
      next(error);
    }
  }

  async createJobPosition(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = createJobPositionSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de puesto invalidos', parseResult.error.errors);
      }

      const dto: CreateJobPositionDto = parseResult.data;
      const position = await departmentsService.createJobPosition(dto, req.tenantId!);

      res.status(201).json({ success: true, data: position, message: 'Puesto creado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async updateJobPosition(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = updateJobPositionSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de puesto invalidos', parseResult.error.errors);
      }

      const dto: UpdateJobPositionDto = parseResult.data;
      const position = await departmentsService.updateJobPosition(req.params.id, dto, req.tenantId!);

      res.json({ success: true, data: position, message: 'Puesto actualizado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async deleteJobPosition(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await departmentsService.deleteJobPosition(req.params.id, req.tenantId!);
      res.json({ success: true, message: 'Puesto eliminado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  // ========== CONTRACTS ==========

  async getContracts(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const queryResult = contractQuerySchema.safeParse(req.query);
      if (!queryResult.success) {
        throw new ValidationError('Parametros de consulta invalidos', queryResult.error.errors);
      }

      const filters: ContractFilters = queryResult.data;
      const result = await contractsService.findAll(req.tenantId!, filters);

      res.json({
        success: true,
        data: result.data,
        meta: { total: result.total, page: filters.page, limit: filters.limit, totalPages: Math.ceil(result.total / (filters.limit || 20)) },
      });
    } catch (error) {
      next(error);
    }
  }

  async getContract(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const contract = await contractsService.findById(req.params.id, req.tenantId!);
      res.json({ success: true, data: contract });
    } catch (error) {
      next(error);
    }
  }

  async createContract(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = createContractSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de contrato invalidos', parseResult.error.errors);
      }

      const dto: CreateContractDto = parseResult.data;
      const contract = await contractsService.create(dto, req.tenantId!, req.user!.userId);

      res.status(201).json({ success: true, data: contract, message: 'Contrato creado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async updateContract(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = updateContractSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de contrato invalidos', parseResult.error.errors);
      }

      const dto: UpdateContractDto = parseResult.data;
      const contract = await contractsService.update(req.params.id, dto, req.tenantId!, req.user!.userId);

      res.json({ success: true, data: contract, message: 'Contrato actualizado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async activateContract(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const contract = await contractsService.activate(req.params.id, req.tenantId!, req.user!.userId);
      res.json({ success: true, data: contract, message: 'Contrato activado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async terminateContract(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = terminateSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos invalidos', parseResult.error.errors);
      }

      const contract = await contractsService.terminate(req.params.id, parseResult.data.termination_date, req.tenantId!, req.user!.userId);
      res.json({ success: true, data: contract, message: 'Contrato terminado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async cancelContract(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const contract = await contractsService.cancel(req.params.id, req.tenantId!, req.user!.userId);
      res.json({ success: true, data: contract, message: 'Contrato cancelado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async deleteContract(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await contractsService.delete(req.params.id, req.tenantId!);
      res.json({ success: true, message: 'Contrato eliminado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  // ========== LEAVE TYPES ==========

  async getLeaveTypes(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const includeInactive = req.query.include_inactive === 'true';
      const leaveTypes = await leavesService.getLeaveTypes(req.tenantId!, includeInactive);
      res.json({ success: true, data: leaveTypes });
    } catch (error) {
      next(error);
    }
  }

  async createLeaveType(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = createLeaveTypeSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de tipo de ausencia invalidos', parseResult.error.errors);
      }

      const dto: CreateLeaveTypeDto = parseResult.data;
      const leaveType = await leavesService.createLeaveType(dto, req.tenantId!);

      res.status(201).json({ success: true, data: leaveType, message: 'Tipo de ausencia creado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async updateLeaveType(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = updateLeaveTypeSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de tipo de ausencia invalidos', parseResult.error.errors);
      }

      const dto: UpdateLeaveTypeDto = parseResult.data;
      const leaveType = await leavesService.updateLeaveType(req.params.id, dto, req.tenantId!);

      res.json({ success: true, data: leaveType, message: 'Tipo de ausencia actualizado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async deleteLeaveType(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await leavesService.deleteLeaveType(req.params.id, req.tenantId!);
      res.json({ success: true, message: 'Tipo de ausencia eliminado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  // ========== LEAVES ==========

  async getLeaves(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const queryResult = leaveQuerySchema.safeParse(req.query);
      if (!queryResult.success) {
        throw new ValidationError('Parametros de consulta invalidos', queryResult.error.errors);
      }

      const filters: LeaveFilters = queryResult.data;
      const result = await leavesService.findAll(req.tenantId!, filters);

      res.json({
        success: true,
        data: result.data,
        meta: { total: result.total, page: filters.page, limit: filters.limit, totalPages: Math.ceil(result.total / (filters.limit || 20)) },
      });
    } catch (error) {
      next(error);
    }
  }

  async getLeave(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const leave = await leavesService.findById(req.params.id, req.tenantId!);
      res.json({ success: true, data: leave });
    } catch (error) {
      next(error);
    }
  }

  async createLeave(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = createLeaveSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de ausencia invalidos', parseResult.error.errors);
      }

      const dto: CreateLeaveDto = parseResult.data;
      const leave = await leavesService.create(dto, req.tenantId!, req.user!.userId);

      res.status(201).json({ success: true, data: leave, message: 'Solicitud de ausencia creada exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async updateLeave(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = updateLeaveSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de ausencia invalidos', parseResult.error.errors);
      }

      const dto: UpdateLeaveDto = parseResult.data;
      const leave = await leavesService.update(req.params.id, dto, req.tenantId!, req.user!.userId);

      res.json({ success: true, data: leave, message: 'Solicitud de ausencia actualizada exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async submitLeave(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const leave = await leavesService.submit(req.params.id, req.tenantId!, req.user!.userId);
      res.json({ success: true, data: leave, message: 'Solicitud enviada exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async approveLeave(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const leave = await leavesService.approve(req.params.id, req.tenantId!, req.user!.userId);
      res.json({ success: true, data: leave, message: 'Solicitud aprobada exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async rejectLeave(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = rejectSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos invalidos', parseResult.error.errors);
      }

      const leave = await leavesService.reject(req.params.id, parseResult.data.reason, req.tenantId!, req.user!.userId);
      res.json({ success: true, data: leave, message: 'Solicitud rechazada' });
    } catch (error) {
      next(error);
    }
  }

  async cancelLeave(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const leave = await leavesService.cancel(req.params.id, req.tenantId!, req.user!.userId);
      res.json({ success: true, data: leave, message: 'Solicitud cancelada exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async deleteLeave(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await leavesService.delete(req.params.id, req.tenantId!);
      res.json({ success: true, message: 'Solicitud eliminada exitosamente' });
    } catch (error) {
      next(error);
    }
  }
}

export const hrController = new HrController();
