import { Response, NextFunction } from 'express';
import { AuthRequest } from '../../shared/middleware/auth';
import { hrService } from './hr.service';
import { ResponseFormatter } from '../../shared/utils/responseFormatter';

export class HRController {
  // ========== EMPLOYEES ==========
  
  async createEmployee(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const employee = await hrService.createEmployee(req.body, req.user!.id);
      res.status(201).json(
        ResponseFormatter.success(employee, 'تم إضافة الموظف بنجاح - Employee created successfully')
      );
    } catch (error) {
      next(error);
    }
  }

  async findAllEmployees(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const rawPage = parseInt(req.query.page as string, 10);
      const rawPageSize = parseInt(req.query.pageSize as string, 10);
      const page = Number.isNaN(rawPage) || rawPage < 1 ? 1 : rawPage;
      const pageSize = Number.isNaN(rawPageSize) || rawPageSize < 1 || rawPageSize > 100 ? 20 : rawPageSize;

      const rawSearch = req.query.search as string;
      const rawDepartmentId = req.query.departmentId as string;
      const rawStatus = req.query.status as string;
      const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;

      const filters: Record<string, string | undefined> = {};
      if (rawSearch && typeof rawSearch === 'string' && rawSearch.trim()) filters.search = rawSearch.trim();
      if (rawDepartmentId && uuidRegex.test(rawDepartmentId)) filters.departmentId = rawDepartmentId;
      if (rawStatus && rawStatus !== 'all' && rawStatus.trim()) filters.status = rawStatus;

      const result = await hrService.findAllEmployees(filters, page, pageSize);
      res.json(ResponseFormatter.paginated(result.employees, result.total, result.page, result.pageSize));
    } catch (error) {
      next(error);
    }
  }

  async findEmployeeById(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const employee = await hrService.findEmployeeById(req.params.id);
      res.json(ResponseFormatter.success(employee));
    } catch (error) {
      next(error);
    }
  }

  async updateEmployee(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const employee = await hrService.updateEmployee(req.params.id, req.body, req.user!.id);
      res.json(ResponseFormatter.success(employee, 'تم تحديث بيانات الموظف - Employee updated'));
    } catch (error) {
      next(error);
    }
  }

  async terminateEmployee(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const { terminationDate, reason } = req.body;
      const employee = await hrService.terminateEmployee(
        req.params.id,
        new Date(terminationDate),
        reason,
        req.user!.id
      );
      res.json(ResponseFormatter.success(employee, 'تم إنهاء خدمة الموظف - Employee terminated'));
    } catch (error) {
      next(error);
    }
  }

  // ========== ATTENDANCE ==========

  async recordAttendance(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const attendance = await hrService.recordAttendance(req.body, req.user!.id);
      res.status(201).json(ResponseFormatter.success(attendance));
    } catch (error) {
      next(error);
    }
  }

  async getAttendance(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const { employeeId } = req.params;
      const month = parseInt(req.query.month as string);
      const year = parseInt(req.query.year as string);
      
      const attendance = await hrService.getAttendance(employeeId, month, year);
      res.json(ResponseFormatter.success(attendance));
    } catch (error) {
      next(error);
    }
  }

  async bulkSyncAttendance(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const { deviceId, records } = req.body;
      const results = await hrService.bulkSyncAttendanceFromDevice(deviceId, records || [], req.user!.id);
      res.json(ResponseFormatter.success(results, 'تم مزامنة الحضور - Attendance synced'));
    } catch (error) {
      next(error);
    }
  }

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

  async createLeaveRequest(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const leave = await hrService.createLeaveRequest(req.body, req.user!.id);
      res.status(201).json(ResponseFormatter.success(leave, 'تم إرسال طلب الإجازة - Leave request submitted'));
    } catch (error) {
      next(error);
    }
  }

  async approveLeave(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const leave = await hrService.approveLeave(req.params.id, req.user!.id, req.user!.id);
      res.json(ResponseFormatter.success(leave, 'تمت الموافقة على الإجازة - Leave approved'));
    } catch (error) {
      next(error);
    }
  }

  async rejectLeave(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const { rejectedReason } = req.body;
      const leave = await hrService.rejectLeave(req.params.id, rejectedReason || '', req.user!.id);
      res.json(ResponseFormatter.success(leave, 'تم رفض طلب الإجازة - Leave rejected'));
    } catch (error) {
      next(error);
    }
  }

  async findAllLeaves(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const page = Math.max(1, parseInt(req.query.page as string) || 1);
      const pageSize = Math.min(100, Math.max(1, parseInt(req.query.pageSize as string) || 20));
      const employeeId = req.query.employeeId as string | undefined;
      const status = req.query.status as string | undefined;
      const result = await hrService.findAllLeaves({ employeeId, status }, page, pageSize);
      res.json(ResponseFormatter.paginated(result.leaves, result.total, result.page, result.pageSize));
    } catch (error) {
      next(error);
    }
  }

  // ========== SALARIES ==========

  async processSalary(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const { employeeId, month, year } = req.body;
      const salary = await hrService.processSalary(employeeId, month, year, req.user!.id);
      res.status(201).json(ResponseFormatter.success(salary, 'تم معالجة الراتب - Salary processed'));
    } catch (error) {
      next(error);
    }
  }

  // ========== DEPARTMENTS ==========
  
  async findAllDepartments(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const departments = await hrService.findAllDepartments();
      res.json(ResponseFormatter.success(departments));
    } catch (error) {
      next(error);
    }
  }

  async getDepartmentsHierarchy(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const tree = await hrService.getDepartmentsHierarchy();
      res.json(ResponseFormatter.success(tree));
    } catch (error) {
      next(error);
    }
  }

  async createDepartment(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const department = await hrService.createDepartment(req.body, req.user!.id);
      res.status(201).json(ResponseFormatter.success(department, 'تم إضافة القسم بنجاح - Department created'));
    } catch (error) {
      next(error);
    }
  }

  async updateDepartment(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const department = await hrService.updateDepartment(req.params.id, req.body, req.user!.id);
      res.json(ResponseFormatter.success(department, 'تم تحديث القسم - Department updated'));
    } catch (error) {
      next(error);
    }
  }

  async deleteDepartment(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      await hrService.deleteDepartment(req.params.id, req.user!.id);
      res.json(ResponseFormatter.success({ success: true }, 'تم حذف القسم - Department deleted'));
    } catch (error) {
      next(error);
    }
  }

  // ========== POSITIONS ==========
  
  async findAllPositions(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const positions = await hrService.findAllPositions();
      res.json(ResponseFormatter.success(positions));
    } catch (error) {
      next(error);
    }
  }

  // ========== LOANS ==========

  async findAllLoans(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const page = Math.max(1, parseInt(req.query.page as string) || 1);
      const pageSize = Math.min(100, Math.max(1, parseInt(req.query.pageSize as string) || 20));
      const employeeId = req.query.employeeId as string | undefined;
      const status = req.query.status as string | undefined;
      const result = await hrService.findAllLoans({ employeeId, status }, page, pageSize);
      res.json(ResponseFormatter.paginated(result.loans, result.total, result.page, result.pageSize));
    } catch (error) {
      next(error);
    }
  }

  async findLoanById(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const loan = await hrService.findLoanById(req.params.id);
      res.json(ResponseFormatter.success(loan));
    } catch (error) {
      next(error);
    }
  }

  async createLoan(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const loan = await hrService.createLoan(req.body, req.user!.id);
      res.status(201).json(ResponseFormatter.success(loan, 'تم إنشاء طلب القرض - Loan request created'));
    } catch (error) {
      next(error);
    }
  }

  async approveLoan(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const { startDate } = req.body;
      const loan = await hrService.approveLoan(req.params.id, req.user!.id, startDate ? new Date(startDate) : new Date(), req.user!.id);
      res.json(ResponseFormatter.success(loan, 'تمت الموافقة على القرض - Loan approved'));
    } catch (error) {
      next(error);
    }
  }

  async rejectLoan(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const { rejectedReason } = req.body;
      const loan = await hrService.rejectLoan(req.params.id, rejectedReason || '', req.user!.id);
      res.json(ResponseFormatter.success(loan, 'تم رفض القرض - Loan rejected'));
    } catch (error) {
      next(error);
    }
  }

  async recordLoanInstallmentPayment(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const { installmentId, paidDate } = req.body;
      const loan = await hrService.recordLoanInstallmentPayment(req.params.id, installmentId, paidDate ? new Date(paidDate) : new Date(), req.user!.id);
      res.json(ResponseFormatter.success(loan, 'تم تسجيل الدفعة - Payment recorded'));
    } catch (error) {
      next(error);
    }
  }

  // ========== PURCHASE REQUESTS ==========

  async findAllPurchaseRequests(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const page = Math.max(1, parseInt(req.query.page as string) || 1);
      const pageSize = Math.min(100, Math.max(1, parseInt(req.query.pageSize as string) || 20));
      const employeeId = req.query.employeeId as string | undefined;
      const status = req.query.status as string | undefined;
      const result = await hrService.findAllPurchaseRequests({ employeeId, status }, page, pageSize);
      res.json(ResponseFormatter.paginated(result.purchaseRequests, result.total, result.page, result.pageSize));
    } catch (error) {
      next(error);
    }
  }

  async findPurchaseRequestById(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const pr = await hrService.findPurchaseRequestById(req.params.id);
      res.json(ResponseFormatter.success(pr));
    } catch (error) {
      next(error);
    }
  }

  async createPurchaseRequest(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const pr = await hrService.createPurchaseRequest(req.body, req.user!.id);
      res.status(201).json(ResponseFormatter.success(pr, 'تم إنشاء طلب الشراء - Purchase request created'));
    } catch (error) {
      next(error);
    }
  }

  async approvePurchaseRequest(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const pr = await hrService.approvePurchaseRequest(req.params.id, req.user!.id, req.user!.id);
      res.json(ResponseFormatter.success(pr, 'تمت الموافقة على طلب الشراء - Purchase request approved'));
    } catch (error) {
      next(error);
    }
  }

  async rejectPurchaseRequest(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const { rejectedReason } = req.body;
      const pr = await hrService.rejectPurchaseRequest(req.params.id, rejectedReason || '', req.user!.id);
      res.json(ResponseFormatter.success(pr, 'تم رفض طلب الشراء - Purchase request rejected'));
    } catch (error) {
      next(error);
    }
  }

  // ========== LEAVE ENTITLEMENTS ==========

  async getLeaveBalance(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const employeeId = req.params.employeeId || req.query.employeeId as string;
      const year = parseInt(req.query.year as string) || new Date().getFullYear();
      const balance = await hrService.getLeaveBalance(employeeId, year);
      res.json(ResponseFormatter.success(balance));
    } catch (error) {
      next(error);
    }
  }

  async findAllLeaveEntitlements(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const employeeId = req.query.employeeId as string | undefined;
      const year = req.query.year ? parseInt(req.query.year as string) : undefined;
      const list = await hrService.findAllLeaveEntitlements(employeeId, year);
      res.json(ResponseFormatter.success(list));
    } catch (error) {
      next(error);
    }
  }

  async upsertLeaveEntitlement(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const ent = await hrService.upsertLeaveEntitlement(req.body, req.user!.id);
      res.json(ResponseFormatter.success(ent, 'تم حفظ رصيد الإجازة - Leave entitlement saved'));
    } catch (error) {
      next(error);
    }
  }

  // ========== EMPLOYEE CONTRACTS ==========

  async findAllEmployeeContracts(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const page = Math.max(1, parseInt(req.query.page as string) || 1);
      const pageSize = Math.min(100, Math.max(1, parseInt(req.query.pageSize as string) || 20));
      const employeeId = req.query.employeeId as string | undefined;
      const status = req.query.status as string | undefined;
      const result = await hrService.findAllEmployeeContracts({ employeeId, status }, page, pageSize);
      res.json(ResponseFormatter.paginated(result.contracts, result.total, result.page, result.pageSize));
    } catch (error) {
      next(error);
    }
  }

  async findEmployeeContractById(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const c = await hrService.findEmployeeContractById(req.params.id);
      res.json(ResponseFormatter.success(c));
    } catch (error) {
      next(error);
    }
  }

  async createEmployeeContract(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const data = { ...req.body, startDate: new Date(req.body.startDate), endDate: req.body.endDate ? new Date(req.body.endDate) : undefined };
      const c = await hrService.createEmployeeContract(data, req.user!.id);
      res.status(201).json(ResponseFormatter.success(c, 'تم إنشاء العقد - Contract created'));
    } catch (error) {
      next(error);
    }
  }

  async updateEmployeeContract(req: AuthRequest, res: Response, next: NextFunction) {
    try {
      const data = { ...req.body, endDate: req.body.endDate ? new Date(req.body.endDate) : undefined };
      const c = await hrService.updateEmployeeContract(req.params.id, data, req.user!.id);
      res.json(ResponseFormatter.success(c, 'تم تحديث العقد - Contract updated'));
    } catch (error) {
      next(error);
    }
  }
}

export const hrController = new HRController();

