<?php
namespace App\Handlers;
use App\Core\Database;
use App\Models\Employee;
use App\Models\LeaveBalance;
use App\Models\LeaveRequest;
use App\Models\LeaveType;
use App\Services\TelegramService;
class ManagerActionHandler
{
private TelegramService $telegramService;
private int $managerChatId; // Telegram Chat ID of the manager interacting
private int $managerTelegramUserId; // Telegram User ID of the manager
private ?int $managerEmployeeId = null; // System's employee ID of the manager
/**
* @param TelegramService $telegramService
* @param int $chatId
* @param int $telegramUserId
*/
public function __construct(TelegramService $telegramService, int $chatId, int $telegramUserId)
{
$this->telegramService = $telegramService;
$this->managerChatId = $chatId;
$this->managerTelegramUserId = $telegramUserId;
$this->loadManagerEmployeeId();
}
private function loadManagerEmployeeId(): void
{
$employeeModel = new Employee(Database::getInstance());
$manager = $employeeModel->findByChatUserId((string) $this->managerTelegramUserId);
if ($manager && $manager->id) {
$this->managerEmployeeId = $manager->id;
// log_message("ManagerActionHandler: Manager Employee ID {$this->managerEmployeeId} loaded for Telegram User ID {$this->managerTelegramUserId}");
} else {
log_message("ManagerActionHandler: No employee record found for manager with Telegram User ID {$this->managerTelegramUserId}.");
}
}
/**
* Handles manager's action (approve/reject) on a leave request.
* @param string $callbackData e.g., "mgrAction_approve_123" or "mgrAction_reject_123"
* @param int $originalMessageId The ID of the message manager interacted with (to edit it)
*/
public function handleApprovalAction(string $callbackData, int $originalMessageId): void
{
if ($this->managerEmployeeId === null) {
$this->telegramService->sendMessage($this->managerChatId, "ขออภัยค่ะ ไม่สามารถดำเนินการได้เนื่องจากไม่พบข้อมูลผู้จัดการ (ID: {$this->managerTelegramUserId}) ของคุณในระบบ");
return;
}
$parts = explode('_', $callbackData);
if (count($parts) !== 3) {
$this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "ข้อมูลการดำเนินการไม่ถูกต้องค่ะ (invalid callback format)");
log_message("ManagerActionHandler: Invalid callback data format: {$callbackData}");
return;
}
$action = $parts[1];
$leaveRequestId = (int) $parts[2];
$leaveRequestModel = new LeaveRequest(Database::getInstance());
$request = $leaveRequestModel->read($leaveRequestId);
if (!$request || !isset($request->id)) {
$this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "ไม่พบคำขอ ID: {$leaveRequestId} ในระบบค่ะ");
return;
}
$requesterEmployeeModel = new Employee(Database::getInstance());
$requester = $requesterEmployeeModel->read($request->employee_id);
if (!$requester || !isset($requester->manager_id) || $requester->manager_id !== $this->managerEmployeeId) {
$this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "คุณไม่มีสิทธิ์ดำเนินการกับคำขอ ID: {$leaveRequestId} นี้ค่ะ");
log_message("Authorization failed: Manager {$this->managerEmployeeId} (Telegram User {$this->managerTelegramUserId}) tried to action request {$leaveRequestId} for employee {$request->employee_id} whose manager is ".($requester->manager_id ?? 'N/A'));
return;
}
if ($request->status !== 'PENDING') {
$this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "คำขอ ID: {$leaveRequestId} ได้รับการดำเนินการไปแล้ว (สถานะปัจจุบัน: {$request->status})");
return;
}
$newStatus = '';
$actionText = '';
$notifyRequesterMessage = ''; // Changed from $notifyRequesterText to avoid confusion with boolean result
// Use the loaded $request object for updates
$requestForUpdate = new LeaveRequest(Database::getInstance());
$requestForUpdate->id = $request->id; // Set ID for updateStatus
if ($action === 'approve') {
$newStatus = 'APPROVED';
$actionText = 'อนุมัติ';
$leaveTypeModel = new LeaveType(Database::getInstance());
$leaveType = $leaveTypeModel->read($request->leave_type_id);
$balanceDeductedSuccessfully = true; // Assume success unless deduction fails
if ($leaveType && $leaveType->deducts_balance) {
$daysToDeduct = LeaveBalance::calculateLeaveDurationInDays($request->start_date, $request->end_date);
$currentYear = (int) date('Y', strtotime($request->start_date));
$leaveBalanceModel = new LeaveBalance(Database::getInstance());
if ($daysToDeduct > 0) {
if (!$leaveBalanceModel->deductFromBalance($request->employee_id, $request->leave_type_id, $currentYear, $daysToDeduct)) {
$balanceDeductedSuccessfully = false;
log_message("Error deducting balance for approved request {$leaveRequestId}. Still marked APPROVED.");
} else {
log_message("Successfully deducted {$daysToDeduct} days for request {$leaveRequestId}.");
}
}
}
if ($requestForUpdate->updateStatus($newStatus, $this->managerEmployeeId)) {
$notifyRequesterMessage = "คำขอ{$this->getRequestTypeText($request->leave_type_id)}ของคุณ (ID: {$leaveRequestId}) ได้รับการ *อนุมัติ* แล้วค่ะ";
if (!$balanceDeductedSuccessfully) {
$notifyRequesterMessage .= "\n*(หมายเหตุ: เกิดปัญหาในการอัปเดตยอดวันลาคงเหลือ กรุณาติดต่อ HR)*";
}
} else {
$this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "เกิดข้อผิดพลาดในการอนุมัติคำขอ ID: {$leaveRequestId}");
return;
}
} elseif ($action === 'reject') {
$newStatus = 'REJECTED';
$actionText = 'ไม่อนุมัติ';
if ($requestForUpdate->updateStatus($newStatus, $this->managerEmployeeId)) {
$notifyRequesterMessage = "คำขอ{$this->getRequestTypeText($request->leave_type_id)}ของคุณ (ID: {$leaveRequestId}) ถูก *ปฏิเสธ* ค่ะ";
} else {
$this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "เกิดข้อผิดพลาดในการไม่อนุมัติคำขอ ID: {$leaveRequestId}");
return;
}
} else {
$this->telegramService->editMessageText($this->managerChatId, $originalMessageId, "การดำเนินการไม่ถูกต้อง ({$action}) สำหรับคำขอ ID: {$leaveRequestId}");
return;
}
// Sanitize for MarkdownV2
$escape = function ($text) {return preg_replace('/([_*\[\]()~`>#\+\-=|{}.!\\\\])/', '\\\\$1', $text);};
$finalMessageToManager = "คุณได้ *{$escape($actionText)}* คำขอ ID: {$escape((string) $leaveRequestId)} เรียบร้อยแล้ว\n";
$finalMessageToManager .= "(ผู้ขอ: {$escape($requester->first_name)}, ประเภท: {$escape($request->leaveType->name ?? 'N/A')}, วันที่: {$escape($request->start_date)} \\- {$escape($request->end_date)})";
// Try to edit the message. If it fails (e.g. message too old, or bot removed from chat), send a new one.
$editSuccess = $this->telegramService->editMessageText($this->managerChatId, $originalMessageId, $finalMessageToManager, null, "MarkdownV2");
if (!$editSuccess || (isset($editSuccess['ok']) && !$editSuccess['ok'])) {
log_message("Failed to edit manager's message (MsgID: {$originalMessageId}). Sending new message. Error: ".json_encode($editSuccess));
$this->telegramService->sendMessage($this->managerChatId, $finalMessageToManager, null, "MarkdownV2");
}
if (!empty($notifyRequesterMessage)) {
$this->notifyRequester($request->employee_id, $leaveRequestId, $newStatus, $notifyRequesterMessage);
}
}
/**
* @param int $leaveTypeId
*/
private function getRequestTypeText(int $leaveTypeId): string
{
$leaveTypeModel = new LeaveType(Database::getInstance());
$leaveType = $leaveTypeModel->read($leaveTypeId);
// Assuming alias 'wfh' is specific to WFH types
if ($leaveType && isset($leaveType->alias) && strtolower($leaveType->alias) === 'wfh') {
return " WFH ";
}
return "ลา";
}
/**
* @param int $requesterEmployeeId
* @param int $leaveRequestId
* @param string $status
* @param string $messageForRequester
* @return null
*/
private function notifyRequester(int $requesterEmployeeId, int $leaveRequestId, string $status, string $messageForRequester): void
{
$employeeModel = new Employee(Database::getInstance());
$requester = $employeeModel->read($requesterEmployeeId);
if ($requester && isset($requester->chat_user_id) && $requester->chat_user_id) {
$requesterChatId = (int) $requester->chat_user_id;
if ($requesterChatId === 0) {
log_message("Could not notify requester (Employee ID: {$requesterEmployeeId}): Invalid chat_user_id '{$requester->chat_user_id}'");
return;
}
$this->telegramService->sendMessage($requesterChatId, $messageForRequester, null, "MarkdownV2");
log_message("Notified requester (Employee ID: {$requesterEmployeeId}, Chat ID: {$requesterChatId}) about request {$leaveRequestId} status: {$status}");
} else {
log_message("Could not notify requester (Employee ID: {$requesterEmployeeId}): User not found or no chat_user_id.");
}
}
}