<?php
// leave_managment/leave_script.php

error_reporting(E_ALL);
ini_set('display_errors', 0); // Suppress errors in output to ensure clean JSON responses

// Only (re)start the session if it's safe to do so -- see sidebar.php for why.
if (session_status() === PHP_SESSION_NONE && !headers_sent()) {
    session_start();
}

require_once '../config.php';

// Authentication Check
if (!isset($_SESSION['user_id'])) {
    if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
        header('Content-Type: application/json');
        echo json_encode(['status' => 'error', 'message' => 'Unauthorized session. Please log in again.']);
        exit;
    }
    header("Location: ../login.php");
    exit;
}

$userId   = intval($_SESSION['user_id']);
$userRole = strtolower($_SESSION['role'] ?? 'staff');
$username = $_SESSION['username'] ?? 'Staff User';

/*
|--------------------------------------------------------------------------
| 1. RESOLVE INITIAL SESSION & EMPLOYEE CONTEXT
|--------------------------------------------------------------------------
*/
$currentEmployeeId   = 0;
$currentEmployeeDept = 0;

$stmt = $conn->prepare("
    SELECT id, department_id 
    FROM employees 
    WHERE user_id = ? 
    LIMIT 1
");
$stmt->bind_param("i", $userId);
$stmt->execute();
$res = $stmt->get_result();

if ($row = $res->fetch_assoc()) {
    $currentEmployeeId   = intval($row['id']);
    $currentEmployeeDept = intval($row['department_id']);
}
$stmt->close();

// Load available leave types
$leaveTypes = [];
$resTypes = $conn->query("SELECT * FROM leave_types ORDER BY name");
if ($resTypes) {
    while ($row = $resTypes->fetch_assoc()) {
        $leaveTypes[$row['id']] = $row;
    }
}

/*
|--------------------------------------------------------------------------
| 2. INTERCEPT DATA PROCESSORS (POST Handlers)
|--------------------------------------------------------------------------
*/
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = $_POST['action'] ?? '';

    /**
     * ACTION A: File Leave Request (file_leave or submit_leave)
     */
    if ($action === 'file_leave' || $action === 'submit_leave') {
        $isAdminPrivileged   = in_array($userRole, ['hr', 'admin', 'superadmin'], true);
        $applicantEmployeeId = intval($_POST['employee_id'] ?? ($_POST['override_employee_id'] ?? $currentEmployeeId));
        $leaveTypeId         = intval($_POST['leave_type_id'] ?? 0);
        $startDate           = trim($_POST['start_date'] ?? '');
        $endDate             = trim($_POST['end_date'] ?? '');
        $reason              = trim($_POST['reason'] ?? '');

        // Validation
        if ($applicantEmployeeId <= 0 || !$leaveTypeId || empty($startDate) || empty($endDate) || empty($reason)) {
            header("Location: ../ess/my_leave.php?err=" . urlencode("All required fields must be completed."));
            exit;
        }

        $startTs = strtotime($startDate);
        $endTs   = strtotime($endDate);

        if (!$startTs || !$endTs || $startTs > $endTs) {
            header("Location: ../ess/my_leave.php?err=" . urlencode("Invalid date range. Start date must occur on or before end date."));
            exit;
        }

        // Prevent standard staff from booking retroactively
        if (!$isAdminPrivileged && $endTs < strtotime(date('Y-m-d'))) {
            header("Location: ../ess/my_leave.php?err=" . urlencode("Timeline Error: You cannot submit a leave request for a period that has passed."));
            exit;
        }

        // Check departmental authority if filing on behalf of another employee (Manager context)
        if (!$isAdminPrivileged && $applicantEmployeeId !== $currentEmployeeId) {
            if ($userRole !== 'manager') {
                header("Location: ../ess/my_leave.php?err=" . urlencode("Unauthorized action."));
                exit;
            }

            $targetStmt = $conn->prepare("SELECT department_id FROM employees WHERE id = ? LIMIT 1");
            $targetStmt->bind_param("i", $applicantEmployeeId);
            $targetStmt->execute();
            $targetEmp = $targetStmt->get_result()->fetch_assoc();
            $targetStmt->close();

            if (!$targetEmp || intval($targetEmp['department_id']) !== $currentEmployeeDept) {
                header("Location: ../ess/my_leave.php?err=" . urlencode("Target staff member is outside your managed department."));
                exit;
            }
        }

        $days = max(1, round(($endTs - $startTs) / 86400) + 1);

        // Overlap Check
        $overlapStmt = $conn->prepare("
            SELECT id FROM leave_requests 
            WHERE employee_id = ? 
              AND (manager_status != 'Rejected' AND hr_status != 'Rejected')
              AND (start_date <= ? AND end_date >= ?)
            LIMIT 1
        ");
        $overlapStmt->bind_param("iss", $applicantEmployeeId, $endDate, $startDate);
        $overlapStmt->execute();
        if ($overlapStmt->get_result()->num_rows > 0) {
            $overlapStmt->close();
            header("Location: ../ess/my_leave.php?err=" . urlencode("Conflicting leave entry detected. An active request already exists for this date range."));
            exit;
        }
        $overlapStmt->close();

        // Leave Balance Validation
        $currentYear = intval(date('Y', $startTs));
        $balStmt = $conn->prepare("
            SELECT (COALESCE(allocated_days, 0.00) + COALESCE(carry_forward, 0.00) - COALESCE(used_days, 0.00)) AS remaining_days
            FROM leave_balances 
            WHERE employee_id = ? AND leave_type_id = ? AND year = ?
            LIMIT 1
        ");
        $balStmt->bind_param("iii", $applicantEmployeeId, $leaveTypeId, $currentYear);
        $balStmt->execute();
        $balRes = $balStmt->get_result()->fetch_assoc();
        $balStmt->close();

        if ($balRes && floatval($balRes['remaining_days']) < $days) {
            header("Location: ../ess/my_leave.php?err=" . urlencode("Insufficient leave balance. Remaining: " . $balRes['remaining_days'] . " days, requested: " . $days . " days."));
            exit;
        }

        // Schema inspect to support variable workflow column naming
        $allTableColumns = [];
        $columnQuery = $conn->query("SHOW COLUMNS FROM leave_requests");
        if ($columnQuery) {
            while ($cRow = $columnQuery->fetch_assoc()) {
                $allTableColumns[] = strtolower($cRow['Field']);
            }
        }

        $insertFields = ['employee_id', 'leave_type_id', 'start_date', 'end_date', 'total_days', 'reason'];
        $bindTypes    = "iissds";
        $bindValues   = [$applicantEmployeeId, $leaveTypeId, $startDate, $endDate, $days, $reason];

        $statusTrackerFields = ['status', 'manager_status', 'hr_status', 'opm_status', 'gm_status', 'director_status'];
        foreach ($statusTrackerFields as $stf) {
            if (in_array($stf, $allTableColumns, true)) {
                $insertFields[] = "`$stf`";
                $bindTypes .= "s";
                
                // Auto-approve manager tier if a manager files for themselves or their team
                if ($stf === 'manager_status' && $userRole === 'manager') {
                    $bindValues[] = 'Approved';
                } else {
                    $bindValues[] = 'Pending';
                }
            }
        }

        $fieldList    = implode(', ', $insertFields);
        $placeholders = implode(', ', array_fill(0, count($insertFields), '?'));
        $sql          = "INSERT INTO leave_requests ({$fieldList}) VALUES ({$placeholders})";

        $insertStmt = $conn->prepare($sql);
        if (!$insertStmt) {
            header("Location: ../ess/my_leave.php?err=" . urlencode("Preparation Error: " . $conn->error));
            exit;
        }

        $bindParams = array_merge([$bindTypes], $bindValues);
        $refs = [];
        foreach ($bindParams as $key => $value) {
            $refs[$key] = &$bindParams[$key];
        }
        call_user_func_array([$insertStmt, 'bind_param'], $refs);

        if ($insertStmt->execute()) {
            $insertStmt->close();
            header("Location: ../ess/my_leave.php?msg=1");
            exit;
        } else {
            $errorMsg = $insertStmt->error;
            $insertStmt->close();
            header("Location: ../ess/my_leave.php?err=" . urlencode("Execution Failure: " . $errorMsg));
            exit;
        }
    }

    /**
     * ACTION B: AJAX Manager Evaluation (manager_evaluate)
     */
    if ($action === 'manager_evaluate') {
        header('Content-Type: application/json');

        if ($userRole !== 'manager' && !in_array($userRole, ['hr', 'admin', 'superadmin'], true)) {
            echo json_encode(['status' => 'error', 'message' => 'Privileges required to evaluate leave requests.']);
            exit;
        }

        $requestId   = intval($_POST['request_id'] ?? 0);
        $statusValue = trim($_POST['status_value'] ?? '');

        if (!$requestId || !in_array($statusValue, ['Approved', 'Rejected'], true)) {
            echo json_encode(['status' => 'error', 'message' => 'Invalid evaluation parameters.']);
            exit;
        }

        // Verify request target and manager scoping
        $reqStmt = $conn->prepare("
            SELECT lr.id, lr.employee_id, emp.department_id, emp.user_id as applicant_user_id
            FROM leave_requests lr
            JOIN employees emp ON emp.id = lr.employee_id
            WHERE lr.id = ? LIMIT 1
        ");
        $reqStmt->bind_param("i", $requestId);
        $reqStmt->execute();
        $req = $reqStmt->get_result()->fetch_assoc();
        $reqStmt->close();

        if (!$req) {
            echo json_encode(['status' => 'error', 'message' => 'Leave request record not found.']);
            exit;
        }

        // Restrict self-approval
        if (intval($req['applicant_user_id']) === $userId) {
            echo json_encode(['status' => 'error', 'message' => 'You cannot evaluate your own leave request.']);
            exit;
        }

        // Enforce departmental scoping for managers
        if ($userRole === 'manager' && intval($req['department_id']) !== $currentEmployeeDept) {
            echo json_encode(['status' => 'error', 'message' => 'Permission denied: Staff member belongs to another department.']);
            exit;
        }

        $updateStmt = $conn->prepare("UPDATE leave_requests SET manager_status = ?, updated_at = NOW() WHERE id = ?");
        $updateStmt->bind_param("si", $statusValue, $requestId);

        if ($updateStmt->execute()) {
            $updateStmt->close();
            echo json_encode(['status' => 'success', 'message' => "Leave request successfully updated to {$statusValue}."]);
            exit;
        } else {
            $err = $updateStmt->error;
            $updateStmt->close();
            echo json_encode(['status' => 'error', 'message' => 'Update execution failed: ' . $err]);
            exit;
        }
    }
}

/*
|--------------------------------------------------------------------------
| 3. GLOBAL DIRECTORIES
|--------------------------------------------------------------------------
*/
$globalEmployees = [];
if (in_array($userRole, ['hr', 'admin', 'superadmin'], true)) {
    $empRes = $conn->query("SELECT id, name FROM employees ORDER BY name ASC");
    while ($empRes && $row = $empRes->fetch_assoc()) {
        $globalEmployees[] = $row;
    }
}

/*
|--------------------------------------------------------------------------
| 4. DATA COMPILATION PIPELINE
|--------------------------------------------------------------------------
*/
$requests = [];

if (in_array($userRole, ['superadmin', 'admin', 'hr'], true)) {
    $stmt = $conn->prepare("
        SELECT lr.*, lt.name AS leave_type, e.name AS employee_name, e.email
        FROM leave_requests lr
        LEFT JOIN leave_types lt ON lt.id = lr.leave_type_id
        LEFT JOIN employees e ON e.id = lr.employee_id
        ORDER BY lr.start_date ASC
    ");
} elseif ($userRole === 'manager') {
    $stmt = $conn->prepare("
        SELECT lr.*, lt.name AS leave_type, e.name AS employee_name, e.email
        FROM leave_requests lr
        LEFT JOIN leave_types lt ON lt.id = lr.leave_type_id
        LEFT JOIN employees e ON e.id = lr.employee_id
        WHERE e.department_id = ?
        ORDER BY lr.start_date ASC
    ");
    if ($stmt) { $stmt->bind_param("i", $currentEmployeeDept); }
} else {
    $stmt = $conn->prepare("
        SELECT lr.*, lt.name AS leave_type, e.name AS employee_name, e.email
        FROM leave_requests lr
        LEFT JOIN leave_types lt ON lt.id = lr.leave_type_id
        LEFT JOIN employees e ON e.id = lr.employee_id
        WHERE lr.employee_id = ?
        ORDER BY lr.start_date ASC
    ");
    if ($stmt) { $stmt->bind_param("i", $currentEmployeeId); }
}

if ($stmt) {
    $stmt->execute();
    $res = $stmt->get_result();
    while ($row = $res->fetch_assoc()) {
        $requests[] = $row;
    }
    $stmt->close();
}

/*
|--------------------------------------------------------------------------
| 5. CALENDAR & TIMELINE CALCULATIONS
|--------------------------------------------------------------------------
*/
$currentMonth = isset($_GET['month']) ? intval($_GET['month']) : intval(date('m'));
$currentYear  = isset($_GET['year']) ? intval($_GET['year']) : intval(date('Y'));
$startDay     = isset($_GET['start_day']) ? intval($_GET['start_day']) : 1;

$baseTimestamp = mktime(0, 0, 0, $currentMonth, $startDay, $currentYear);
$monthLabel    = date('F Y', $baseTimestamp);

$timelineDates = [];
for ($i = 0; $i < 7; $i++) {
    $loopTime = strtotime("+$i days", $baseTimestamp);
    $timelineDates[] = [
        'date_string' => date('Y-m-d', $loopTime),
        'day_num'     => date('d', $loopTime),
        'day_name'    => date('D', $loopTime),
        'is_today'    => (date('Y-m-d', $loopTime) === date('Y-m-d'))
    ];
}

$prevWeekTimestamp = strtotime("-7 days", $baseTimestamp);
$nextWeekTimestamp = strtotime("+7 days", $baseTimestamp);

$prevQuery = sprintf("month=%d&year=%d&start_day=%d", date('m', $prevWeekTimestamp), date('Y', $prevWeekTimestamp), date('d', $prevWeekTimestamp));
$nextQuery = sprintf("month=%d&year=%d&start_day=%d", date('m', $nextWeekTimestamp), date('Y', $nextWeekTimestamp), date('d', $nextWeekTimestamp));

// Visual Formatting Mapping Matrix
$colorMap = [
    'annual leave'      => ['bg' => 'bg-emerald-50 border-emerald-300 text-emerald-900', 'dot' => 'bg-emerald-500'],
    'annual'            => ['bg' => 'bg-emerald-50 border-emerald-300 text-emerald-900', 'dot' => 'bg-emerald-500'],
    'sick leave'        => ['bg' => 'bg-rose-50 border-rose-300 text-rose-900', 'dot' => 'bg-rose-500'],
    'sick'              => ['bg' => 'bg-rose-50 border-rose-300 text-rose-900', 'dot' => 'bg-rose-500'],
    'emergency leave'   => ['bg' => 'bg-amber-50 border-amber-300 text-amber-900', 'dot' => 'bg-amber-500'],
    'emergency'         => ['bg' => 'bg-amber-50 border-amber-300 text-amber-900', 'dot' => 'bg-amber-500'],
    'compensatory leave'=> ['bg' => 'bg-cyan-50 border-cyan-300 text-cyan-900', 'dot' => 'bg-cyan-500'],
    'compensatory'      => ['bg' => 'bg-cyan-50 border-cyan-300 text-cyan-900', 'dot' => 'bg-cyan-500'],
    'personal leave'    => ['bg' => 'bg-lime-50 border-lime-300 text-lime-900', 'dot' => 'bg-lime-500'],
    'personal'          => ['bg' => 'bg-lime-50 border-lime-300 text-lime-900', 'dot' => 'bg-lime-500'],
    'marriage leave'    => ['bg' => 'bg-orange-50 border-orange-300 text-orange-900', 'dot' => 'bg-orange-500'],
    'marriage'          => ['bg' => 'bg-orange-50 border-orange-300 text-orange-900', 'dot' => 'bg-orange-500'],
    'maternity leave'   => ['bg' => 'bg-pink-50 border-pink-300 text-pink-900', 'dot' => 'bg-pink-500'],
    'maternity'         => ['bg' => 'bg-pink-50 border-pink-300 text-pink-900', 'dot' => 'bg-pink-500'],
    'paternity leave'   => ['bg' => 'bg-blue-50 border-blue-300 text-blue-900', 'dot' => 'bg-blue-500'],
    'paternity'         => ['bg' => 'bg-blue-50 border-blue-300 text-blue-900', 'dot' => 'bg-blue-500'],
    'bereavement leave' => ['bg' => 'bg-slate-100 border-slate-300 text-slate-900', 'dot' => 'bg-slate-500'],
    'bereavement'       => ['bg' => 'bg-slate-100 border-slate-300 text-slate-900', 'dot' => 'bg-slate-500'],
    'study leave'       => ['bg' => 'bg-purple-50 border-purple-300 text-purple-900', 'dot' => 'bg-purple-500'],
    'study'             => ['bg' => 'bg-purple-50 border-purple-300 text-purple-900', 'dot' => 'bg-purple-500'],
];
$defaultColor = ['bg' => 'bg-indigo-50 border-indigo-200 text-indigo-950', 'dot' => 'bg-indigo-500'];

// Active Workflow Stages Matrix
$activeWorkflowStages = [];
$stageRes = $conn->query("SELECT DISTINCT checking_column, stage_name FROM leave_approval_stages ORDER BY stage_order ASC");
if ($stageRes) {
    while ($sRow = $stageRes->fetch_assoc()) {
        $activeWorkflowStages[$sRow['checking_column']] = $sRow['stage_name'];
    }
}
if (empty($activeWorkflowStages)) {
    $activeWorkflowStages = ['manager_status' => 'Manager', 'hr_status' => 'HR'];
}

// Group Requests by Employee
$groupedRequests = [];
foreach ($requests as $req) {
    $empName = $req['employee_name'] ?? 'Unknown Employee';
    if (!isset($groupedRequests[$empName])) {
        $groupedRequests[$empName] = [];
    }
    $groupedRequests[$empName][] = $req;
}

if (empty($groupedRequests) && isset($_SESSION['user_id'])) {
    $currentName = $_SESSION['name'] ?? $username;
    $groupedRequests[$currentName] = [];
}