<?php
/**
 * Enterprise HRM ERP System - Attendance Data Isolation
 * Role-based attendance access control with hierarchy support
 * 
 * RULES:
 * - Admin: Can view all HRs and all Employees
 * - HR: Can view self + employees under them (manager_id = HR's employee_id)
 * - Employee: Can view only self
 */

if (!defined('HRM_ACCESS')) {
    die('Direct access not allowed');
}

require_once __DIR__ . '/data_isolation.php';

/**
 * Get current user's employee_id (if linked)
 */
function getCurrentEmployeeId() {
    startSession();
    
    if (!isset($_SESSION['user_id'])) {
        return null;
    }
    
    // Check if employee_id is in session
    if (isset($_SESSION['employee_id'])) {
        return $_SESSION['employee_id'];
    }
    
    // Load from database
    try {
        $db = getDB();
        $stmt = $db->prepare("SELECT employee_id FROM users WHERE user_id = ? AND employee_id IS NOT NULL");
        $stmt->execute([$_SESSION['user_id']]);
        $user = $stmt->fetch();
        
        if ($user && $user['employee_id']) {
            $_SESSION['employee_id'] = $user['employee_id'];
            return $user['employee_id'];
        }
    } catch (Exception $e) {
        error_log("Error getting current employee ID: " . $e->getMessage());
    }
    
    return null;
}

/**
 * Get HR Admin's employee_id
 */
function getHRAdminEmployeeId() {
    startSession();
    
    if (!isHRAdmin()) {
        return null;
    }
    
    // Try to get from session
    if (isset($_SESSION['hr_employee_id'])) {
        return $_SESSION['hr_employee_id'];
    }
    
    // Load from database - HR Admin's user email should match employee email
    try {
        $db = getDB();
        $email = $_SESSION['email'] ?? '';
        
        if (empty($email)) {
            return null;
        }
        
        $stmt = $db->prepare("
            SELECT employee_id 
            FROM employees 
            WHERE email = ? AND employment_status = 'active'
            LIMIT 1
        ");
        $stmt->execute([$email]);
        $employee = $stmt->fetch();
        
        if ($employee) {
            $_SESSION['hr_employee_id'] = $employee['employee_id'];
            return $employee['employee_id'];
        }
    } catch (Exception $e) {
        error_log("Error getting HR Admin employee ID: " . $e->getMessage());
    }
    
    return null;
}

/**
 * Get list of employee IDs that current user can view/manage
 * Returns array of employee_ids based on role hierarchy
 */
function getAccessibleEmployeeIds() {
    startSession();
    
    // Super Admin: All employees
    if (isSuperAdmin()) {
        try {
            $db = getDB();
            $siteFilter = getSiteFilter();
            
            $sql = "SELECT employee_id FROM employees WHERE employment_status = 'active'";
            $params = [];
            
            if ($siteFilter !== null) {
                $sql .= " AND site_id = ?";
                $params[] = $siteFilter;
            }
            
            $stmt = $db->prepare($sql);
            $stmt->execute($params);
            return $stmt->fetchAll(PDO::FETCH_COLUMN);
        } catch (Exception $e) {
            error_log("Error getting accessible employee IDs (Super Admin): " . $e->getMessage());
            return [];
        }
    }
    
    // HR Admin: Self + employees under them (manager_id = HR's employee_id)
    if (isHRAdmin()) {
        try {
            $db = getDB();
            $hrEmployeeId = getHRAdminEmployeeId();
            $siteId = getCurrentSiteId();
            
            if (!$hrEmployeeId || !$siteId) {
                return [];
            }
            
            // Get HR's own employee_id + all employees where manager_id = HR's employee_id
            $stmt = $db->prepare("
                SELECT employee_id 
                FROM employees 
                WHERE employment_status = 'active' 
                AND site_id = ?
                AND (employee_id = ? OR manager_id = ?)
            ");
            $stmt->execute([$siteId, $hrEmployeeId, $hrEmployeeId]);
            return $stmt->fetchAll(PDO::FETCH_COLUMN);
        } catch (Exception $e) {
            error_log("Error getting accessible employee IDs (HR Admin): " . $e->getMessage());
            return [];
        }
    }
    
    // Employee: Only self
    if (isEmployee()) {
        $employeeId = getCurrentEmployeeId();
        return $employeeId ? [$employeeId] : [];
    }
    
    return [];
}

/**
 * Get SQL WHERE clause for employee access filtering
 */
function getEmployeeAccessFilterSQL($employeeColumn = 'e.employee_id') {
    $employeeIds = getAccessibleEmployeeIds();
    
    if (empty($employeeIds)) {
        return '1=0'; // No access
    }
    
    if (count($employeeIds) === 1) {
        return $employeeColumn . ' = ' . (int)$employeeIds[0];
    }
    
    $ids = implode(',', array_map('intval', $employeeIds));
    return $employeeColumn . ' IN (' . $ids . ')';
}

/**
 * Get parameters for employee access filter (for prepared statements)
 */
function getEmployeeAccessFilterParams() {
    return getAccessibleEmployeeIds();
}

/**
 * Check if user can view/manage attendance for specific employee
 */
function canViewEmployeeAttendance($employeeId) {
    startSession();
    
    // Super Admin: Can view all
    if (isSuperAdmin()) {
        return true;
    }
    
    // Employee: Can only view self
    if (isEmployee()) {
        $currentEmployeeId = getCurrentEmployeeId();
        return $currentEmployeeId && $currentEmployeeId == $employeeId;
    }
    
    // HR Admin: Can view self + employees under them
    if (isHRAdmin()) {
        $accessibleIds = getAccessibleEmployeeIds();
        return in_array($employeeId, $accessibleIds);
    }
    
    return false;
}

/**
 * Require attendance access (redirect if not allowed)
 */
function requireAttendanceAccess($employeeId) {
    if (!canViewEmployeeAttendance($employeeId)) {
        $_SESSION['error'] = 'You do not have permission to access this employee attendance.';
        header('Location: ' . BASE_URL . '/dashboard.php');
        exit;
    }
}

/**
 * Get employees list for attendance form dropdown
 * Respects role hierarchy
 */
function getAttendanceEmployeesList() {
    startSession();
    
    try {
        $db = getDB();
        $siteId = getCurrentSiteId();
        
        if (!$siteId) {
            return [];
        }
        
        // Super Admin: All employees in selected site
        if (isSuperAdmin()) {
            $stmt = $db->prepare("
                SELECT employee_id, employee_code, first_name, middle_name, last_name, employment_status
                FROM employees 
                WHERE employment_status = 'active' AND site_id = ?
                ORDER BY employee_code, first_name, last_name
            ");
            $stmt->execute([$siteId]);
            return $stmt->fetchAll();
        }
        
        // HR Admin: Self + employees under them
        if (isHRAdmin()) {
            $hrEmployeeId = getHRAdminEmployeeId();
            
            if (!$hrEmployeeId) {
                return [];
            }
            
            $stmt = $db->prepare("
                SELECT employee_id, employee_code, first_name, middle_name, last_name, employment_status
                FROM employees 
                WHERE employment_status = 'active' 
                AND site_id = ?
                AND (employee_id = ? OR manager_id = ?)
                ORDER BY employee_code, first_name, last_name
            ");
            $stmt->execute([$siteId, $hrEmployeeId, $hrEmployeeId]);
            return $stmt->fetchAll();
        }
        
        // Employee: Only self
        if (isEmployee()) {
            $employeeId = getCurrentEmployeeId();
            
            if (!$employeeId) {
                return [];
            }
            
            $stmt = $db->prepare("
                SELECT employee_id, employee_code, first_name, middle_name, last_name, employment_status
                FROM employees 
                WHERE employee_id = ? AND employment_status = 'active'
            ");
            $stmt->execute([$employeeId]);
            return $stmt->fetchAll();
        }
        
        return [];
    } catch (Exception $e) {
        error_log("Error getting attendance employees list: " . $e->getMessage());
        return [];
    }
}

/**
 * Check if check-in already exists for employee on date
 */
function hasCheckInForDate($employeeId, $date, $siteId) {
    try {
        $db = getDB();
        $stmt = $db->prepare("
            SELECT attendance_id, check_in_time 
            FROM attendance 
            WHERE employee_id = ? AND attendance_date = ? AND site_id = ? AND check_in_time IS NOT NULL
        ");
        $stmt->execute([$employeeId, $date, $siteId]);
        return (bool)$stmt->fetch();
    } catch (Exception $e) {
        error_log("Error checking check-in: " . $e->getMessage());
        return false;
    }
}

/**
 * Check if check-out is allowed (check-in must exist)
 */
function canCheckOut($employeeId, $date, $siteId) {
    try {
        $db = getDB();
        $stmt = $db->prepare("
            SELECT attendance_id, check_in_time, check_out_time 
            FROM attendance 
            WHERE employee_id = ? AND attendance_date = ? AND site_id = ?
        ");
        $stmt->execute([$employeeId, $date, $siteId]);
        $attendance = $stmt->fetch();
        
        if (!$attendance) {
            return false; // No attendance record
        }
        
        if (empty($attendance['check_in_time'])) {
            return false; // No check-in
        }
        
        if (!empty($attendance['check_out_time'])) {
            return false; // Already checked out
        }
        
        return true;
    } catch (Exception $e) {
        error_log("Error checking check-out permission: " . $e->getMessage());
        return false;
    }
}

/**
 * Get attendance status based on check-in/check-out times
 */
function calculateAttendanceStatus($checkInTime, $checkOutTime, $expectedCheckIn = '09:00:00') {
    if (empty($checkInTime)) {
        return 'absent';
    }
    
    // Check if late (check-in after expected time)
    $checkInHour = (int)date('H', strtotime($checkInTime));
    $checkInMinute = (int)date('i', strtotime($checkInTime));
    $expectedHour = (int)date('H', strtotime($expectedCheckIn));
    $expectedMinute = (int)date('i', strtotime($expectedCheckIn));
    
    $checkInMinutes = ($checkInHour * 60) + $checkInMinute;
    $expectedMinutes = ($expectedHour * 60) + $expectedMinute;
    
    // Late if check-in is more than 15 minutes after expected time
    if ($checkInMinutes > ($expectedMinutes + 15)) {
        return 'late';
    }
    
    // Check if half day (less than 4 hours worked)
    if (!empty($checkOutTime)) {
        $checkIn = new DateTime($checkInTime);
        $checkOut = new DateTime($checkOutTime);
        $diff = $checkIn->diff($checkOut);
        $hours = $diff->h + ($diff->i / 60);
        
        if ($hours < 4) {
            return 'half_day';
        }
    }
    
    return 'present';
}

/**
 * Calculate lateness in minutes
 */
function calculateLateness($checkInTime, $expectedCheckIn = '09:00:00') {
    if (empty($checkInTime)) {
        return 0;
    }
    
    $checkIn = new DateTime($checkInTime);
    $expected = new DateTime(date('Y-m-d') . ' ' . $expectedCheckIn);
    
    if ($checkIn <= $expected) {
        return 0; // Not late
    }
    
    $diff = $checkIn->diff($expected);
    return ($diff->h * 60) + $diff->i;
}

/**
 * Calculate early leaving in minutes
 */
function calculateEarlyLeaving($checkOutTime, $expectedCheckOut = '18:00:00') {
    if (empty($checkOutTime)) {
        return 0;
    }
    
    $checkOut = new DateTime($checkOutTime);
    $expected = new DateTime(date('Y-m-d') . ' ' . $expectedCheckOut);
    
    if ($checkOut >= $expected) {
        return 0; // Not early
    }
    
    $diff = $expected->diff($checkOut);
    return ($diff->h * 60) + $diff->i;
}
