<?php
require_once '../includes/auth.php';
require_once '../includes/db.php';

header('Content-Type: application/json');

if (!isLoggedIn()) {
    echo json_encode(['success' => false, 'message' => 'Unauthorized']);
    exit;
}

if (!isModuleEnabled('leaves')) {
    echo json_encode(['success' => false, 'message' => 'Leaves module is disabled']);
    exit;
}

$data = json_decode(file_get_contents('php://input'), true);
$action = $_POST['action'] ?? $data['action'] ?? $_GET['action'] ?? '';

$company_id = $_SESSION['company_id'];
$user_id = $_SESSION['user_id'];

// Helper to get employee ID from user ID
function getEmployeeId($userId, $companyId) {
    $emp = fetch("SELECT id, reporting_manager_id FROM employees WHERE user_id = ? AND company_id = ?", [$userId, $companyId]);
    return $emp;
}

// Helper to count public holidays in range
function countHolidaysInRange($startDate, $endDate, $companyId) {
    $count = fetchValue("
        SELECT COUNT(*) FROM public_holidays 
        WHERE company_id = ? AND holiday_date BETWEEN ? AND ?
    ", [$companyId, $startDate, $endDate]);
    return intval($count);
}

// Helper to calculate leave duration in days
function calculateLeaveDuration($durationType, $startDate, $endDate, $companyId) {
    if ($durationType === 'half_day') {
        return 0.5;
    }
    if ($durationType === 'short_leave') {
        return 0.25; // Counts as 1/4 of a day
    }
    
    // Full days
    $start = new DateTime($startDate);
    $end = new DateTime($endDate);
    $diff = $start->diff($end);
    $totalDays = $diff->days + 1;
    
    // Deduct public holidays in range
    $holidays = countHolidaysInRange($startDate, $endDate, $companyId);
    $netDays = $totalDays - $holidays;
    
    return $netDays > 0 ? $netDays : 0;
}

// Helper to calculate employee's leave balance
function getLeaveBalance($empId, $leaveType, $companyId) {
    // 1. Get annual limit
    $config = fetch("SELECT days_per_year FROM leave_configurations WHERE company_id = ? AND leave_type = ?", [$companyId, $leaveType]);
    $limit = $config ? intval($config['days_per_year']) : 0;
    
    // 2. Sum approved leaves for this year
    $yearStart = date('Y') . '-01-01';
    $yearEnd = date('Y') . '-12-31';
    
    $requests = fetchAll("
        SELECT duration_type, start_date, end_date 
        FROM leave_requests 
        WHERE employee_id = ? AND company_id = ? AND leave_type = ? AND status = 'approved'
          AND start_date BETWEEN ? AND ?
    ", [$empId, $companyId, $leaveType, $yearStart, $yearEnd]);
    
    $taken = 0.0;
    foreach ($requests as $r) {
        $taken += calculateLeaveDuration($r['duration_type'], $r['start_date'], $r['end_date'], $companyId);
    }
    
    return [
        'limit' => $limit,
        'taken' => $taken,
        'remaining' => max(0, $limit - $taken)
    ];
}

switch ($action) {
    case 'balances':
        $emp = getEmployeeId($user_id, $company_id);
        if (!$emp) {
            echo json_encode(['success' => false, 'message' => 'Employee profile not found']);
            exit;
        }
        $empId = $emp['id'];

        $leaveTypes = ['casual', 'annual', 'sick', 'maternity', 'paternity'];
        $balances = [];
        foreach ($leaveTypes as $type) {
            $balances[$type] = getLeaveBalance($empId, $type, $company_id);
        }

        echo json_encode(['success' => true, 'balances' => $balances]);
        break;

    case 'apply':
        $emp = getEmployeeId($user_id, $company_id);
        if (!$emp) {
            echo json_encode(['success' => false, 'message' => 'Employee profile not found']);
            exit;
        }
        $empId = $emp['id'];
        $reportingManagerId = $emp['reporting_manager_id'];

        if (!$reportingManagerId) {
            echo json_encode(['success' => false, 'message' => 'You do not have a Reporting Manager assigned. Please request a manager to set one for you first.']);
            exit;
        }

        $leaveType = $_POST['leave_type'] ?? $data['leave_type'] ?? '';
        $durationType = $_POST['duration_type'] ?? $data['duration_type'] ?? 'full';
        $startDate = $_POST['start_date'] ?? $data['start_date'] ?? null;
        $endDate = $_POST['end_date'] ?? $data['end_date'] ?? null;
        $halfDayType = $_POST['half_day_type'] ?? $data['half_day_type'] ?? null;
        $shortLeaveStart = $_POST['short_leave_start'] ?? $data['short_leave_start'] ?? null;
        $shortLeaveEnd = $_POST['short_leave_end'] ?? $data['short_leave_end'] ?? null;
        $reason = $_POST['reason'] ?? $data['reason'] ?? '';

        if (!$leaveType || !$startDate) {
            echo json_encode(['success' => false, 'message' => 'Missing required fields']);
            exit;
        }

        if ($durationType !== 'full') {
            $endDate = $startDate; // Must be same day
        }

        // Validate leave limits
        $requestedDays = calculateLeaveDuration($durationType, $startDate, $endDate, $company_id);
        $bal = getLeaveBalance($empId, $leaveType, $company_id);
        
        if ($leaveType !== 'unpaid' && ($bal['remaining'] < $requestedDays)) {
            echo json_encode(['success' => false, 'message' => "Insufficient leave balance for {$leaveType} leaves. Requested: {$requestedDays} days. Available: {$bal['remaining']} days."]);
            exit;
        }

        try {
            query("
                INSERT INTO leave_requests (
                    employee_id, company_id, reporting_manager_id, leave_type, duration_type, 
                    start_date, end_date, half_day_type, short_leave_start, short_leave_end, reason, status
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending')
            ", [
                $empId, $company_id, $reportingManagerId, $leaveType, $durationType, 
                $startDate, $endDate, $halfDayType, $shortLeaveStart, $shortLeaveEnd, $reason
            ]);

            // Notify manager
            $empName = fetchValue("SELECT name FROM employees WHERE id = ?", [$empId]);
            createNotification(
                $company_id, 
                'info', 
                'New Leave Request', 
                "{$empName} has requested a {$durationType} leave for {$startDate}.", 
                url('leaves'), 
                'leave_req_' . time()
            );

            logAudit('Leave Request Submitted', "Employee $empId submitted a request for $leaveType leave ($durationType) on $startDate.");
            echo json_encode(['success' => true, 'message' => 'Leave request submitted successfully to your reporting manager']);
        } catch (Exception $e) {
            echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]);
        }
        break;

    case 'action_request':
        $reqId = $_POST['id'] ?? $data['id'] ?? null;
        $status = $_POST['status'] ?? $data['status'] ?? ''; // 'approved' or 'rejected'
        $comment = $_POST['comment'] ?? $data['comment'] ?? '';

        if (!$reqId || !in_array($status, ['approved', 'rejected'])) {
            echo json_encode(['success' => false, 'message' => 'Invalid inputs']);
            exit;
        }

        // Fetch request and check authority
        $req = fetch("SELECT * FROM leave_requests WHERE id = ? AND company_id = ?", [$reqId, $company_id]);
        if (!$req) {
            echo json_encode(['success' => false, 'message' => 'Request not found']);
            exit;
        }

        // Must be the assigned reporting manager
        if ($req['reporting_manager_id'] != $user_id) {
            echo json_encode(['success' => false, 'message' => 'Unauthorized. Only the assigned Reporting Manager can action this request.']);
            exit;
        }

        try {
            query("
                UPDATE leave_requests 
                SET status = ?, actioned_by = ?, action_reason = ? 
                WHERE id = ?
            ", [$status, $user_id, $comment, $reqId]);

            // Notify employee (user account linked to employee)
            $emp = fetch("SELECT name, user_id FROM employees WHERE id = ?", [$req['employee_id']]);
            if ($emp && $emp['user_id']) {
                createNotification(
                    $company_id,
                    $status === 'approved' ? 'success' : 'error',
                    "Leave Request " . ucfirst($status),
                    "Your leave request for {$req['start_date']} has been {$status}.",
                    url('leaves')
                );
            }

            logAudit("Leave Request " . ucfirst($status), "Request ID $reqId was $status by user $user_id.");
            echo json_encode(['success' => true, 'message' => "Request " . ucfirst($status) . " successfully"]);
        } catch (Exception $e) {
            echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]);
        }
        break;

    case 'save_config':
        if (!hasRole(['owner', 'manager'])) {
            echo json_encode(['success' => false, 'message' => 'Unauthorized']);
            exit;
        }

        $configs = $_POST['config'] ?? $data['config'] ?? [];
        try {
            global $pdo;
            $pdo->beginTransaction();
            foreach ($configs as $type => $days) {
                query("
                    INSERT INTO leave_configurations (company_id, leave_type, days_per_year) 
                    VALUES (?, ?, ?) 
                    ON DUPLICATE KEY UPDATE days_per_year = ?
                ", [$company_id, $type, intval($days), intval($days)]);
            }
            $pdo->commit();
            logAudit('Leave Configurations Updated', 'Updated annual leave limits.');
            echo json_encode(['success' => true, 'message' => 'Leave limits updated successfully']);
        } catch (Exception $e) {
            if ($pdo->inTransaction()) $pdo->rollBack();
            echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]);
        }
        break;

    case 'add_holiday':
        if (!hasRole(['owner', 'manager'])) {
            echo json_encode(['success' => false, 'message' => 'Unauthorized']);
            exit;
        }

        $date = $_POST['holiday_date'] ?? $data['holiday_date'] ?? '';
        $name = $_POST['holiday_name'] ?? $data['holiday_name'] ?? '';

        if (!$date || !$name) {
            echo json_encode(['success' => false, 'message' => 'Missing parameters']);
            exit;
        }

        try {
            query("
                INSERT INTO public_holidays (company_id, holiday_date, name) 
                VALUES (?, ?, ?)
                ON DUPLICATE KEY UPDATE name = ?
            ", [$company_id, $date, $name, $name]);
            
            logAudit('Public Holiday Added', "Added $name on $date");
            echo json_encode(['success' => true, 'message' => 'Public holiday added successfully']);
        } catch (Exception $e) {
            echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]);
        }
        break;

    case 'delete_holiday':
        if (!hasRole(['owner', 'manager'])) {
            echo json_encode(['success' => false, 'message' => 'Unauthorized']);
            exit;
        }

        $id = $_POST['id'] ?? $data['id'] ?? null;
        if (!$id) {
            echo json_encode(['success' => false, 'message' => 'Missing ID']);
            exit;
        }

        try {
            query("DELETE FROM public_holidays WHERE id = ? AND company_id = ?", [$id, $company_id]);
            logAudit('Public Holiday Deleted', "Deleted holiday record $id");
            echo json_encode(['success' => true, 'message' => 'Public holiday deleted successfully']);
        } catch (Exception $e) {
            echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]);
        }
        break;

    case 'company_records':
        if (!hasRole(['owner', 'manager'])) {
            echo json_encode(['success' => false, 'message' => 'Unauthorized']);
            exit;
        }

        $search = $_GET['search'] ?? $data['search'] ?? '';
        $filter_start_date = $_GET['start_date'] ?? $data['start_date'] ?? '';
        $filter_end_date = $_GET['end_date'] ?? $data['end_date'] ?? '';

        // Fetch matching employees
        $queryStr = "SELECT id, name FROM employees WHERE company_id = ?";
        $params = [$company_id];
        
        if (!empty($search)) {
            $search_clean = trim($search);
            if (preg_match('/^emp-(\d+)$/i', $search_clean, $matches)) {
                $search_id = intval($matches[1]);
                $queryStr .= " AND (id = ? OR name LIKE ?)";
                $params[] = $search_id;
                $params[] = '%' . $search_clean . '%';
            } else if (is_numeric($search_clean)) {
                $queryStr .= " AND (id = ? OR name LIKE ?)";
                $params[] = intval($search_clean);
                $params[] = '%' . $search_clean . '%';
            } else {
                $queryStr .= " AND name LIKE ?";
                $params[] = '%' . $search_clean . '%';
            }
        }
        
        $employees = fetchAll($queryStr, $params);
        $records = [];
        $leaveTypes = ['casual', 'annual', 'sick', 'maternity', 'paternity'];

        foreach ($employees as $emp) {
            $empId = $emp['id'];
            
            // Get Balances for all types
            $balances = [];
            foreach ($leaveTypes as $type) {
                $balances[$type] = getLeaveBalance($empId, $type, $company_id);
            }

            // Get leave history for this employee
            $historyQuery = "
                SELECT id, leave_type, duration_type, start_date, end_date, reason, status
                FROM leave_requests
                WHERE employee_id = ? AND company_id = ?
            ";
            $historyParams = [$empId, $company_id];

            if (!empty($filter_start_date)) {
                $historyQuery .= " AND start_date >= ?";
                $historyParams[] = $filter_start_date;
            }
            if (!empty($filter_end_date)) {
                $historyQuery .= " AND end_date <= ?";
                $historyParams[] = $filter_end_date;
            }

            $historyQuery .= " ORDER BY start_date DESC";
            $history = fetchAll($historyQuery, $historyParams);

            // Calculate duration strings for UI
            foreach ($history as &$h) {
                $h['duration_days'] = calculateLeaveDuration($h['duration_type'], $h['start_date'], $h['end_date'], $company_id);
            }

            $records[] = [
                'employee_id' => $empId,
                'employee_code' => "EMP-" . str_pad($empId, 4, '0', STR_PAD_LEFT),
                'employee_name' => $emp['name'],
                'balances' => $balances,
                'history' => $history
            ];
        }

        echo json_encode([
            'success' => true,
            'records' => $records
        ]);
        break;

    default:
        echo json_encode(['success' => false, 'message' => 'Invalid action']);
        break;
}
