<?php
if (session_status() === PHP_SESSION_NONE && !headers_sent()) {
    session_start();
}

require '../config.php';

// Auth Guard - Access Control for Superadmin and HR
if (!isset($_SESSION['user_id'])) {
    header("Location: ../login.php");
    exit;
}

$userRole = strtolower(trim($_SESSION['role'] ?? 'staff'));
$allowedRoles = ['admin', 'superadmin', 'hr'];

if (!in_array($userRole, $allowedRoles, true)) {
    die("Unauthorized access context.");
}

/**
 * Executes Monthly Carry Forward by linking previous circle balances
 * to the next payroll circle ID in leave_balances table.
 */
function executeMonthlyLeaveCarryForward($conn, $sourceCircleId, $maxCap = null) {
    // 1. Fetch Source Circle Details
    $cStmt = $conn->prepare("SELECT * FROM payroll_circles WHERE id = ? LIMIT 1");
    $cStmt->bind_param("i", $sourceCircleId);
    $cStmt->execute();
    $sourceCircle = $cStmt->get_result()->fetch_assoc();
    $cStmt->close();

    if (!$sourceCircle) {
        return false;
    }

    $sourceMonth = (int)$sourceCircle['payroll_month'];
    $sourceYear  = (int)$sourceCircle['payroll_year'];

    // 2. Determine Next Circle Month & Year (Monthly Rollover)
    $targetMonth = $sourceMonth + 1;
    $targetYear  = $sourceYear;
    if ($targetMonth > 12) {
        $targetMonth = 1;
        $targetYear++;
    }

    // 3. Find or Create Next Payroll Circle Target
    $targetCircleId = null;
    $tStmt = $conn->prepare("SELECT id FROM payroll_circles WHERE payroll_month = ? AND payroll_year = ? LIMIT 1");
    $tStmt->bind_param("ii", $targetMonth, $targetYear);
    $tStmt->execute();
    $tRes = $tStmt->get_result()->fetch_assoc();
    $tStmt->close();

    if ($tRes) {
        $targetCircleId = intval($tRes['id']);
    } else {
        // Create next circle automatically (Cutoff e.g., 21st to 20th)
        $startDate = sprintf("%04d-%02d-21", $sourceYear, $sourceMonth);
        $endDate   = sprintf("%04d-%02d-20", $targetYear, $targetMonth);
        $circleName = "Cycle - " . date("M Y", strtotime($startDate));

        $insCircle = $conn->prepare("INSERT INTO payroll_circles (name, payroll_month, payroll_year, start_date, end_date, status) VALUES (?, ?, ?, ?, ?, 'pending_approval')");
        $insCircle->bind_param("siiss", $circleName, $targetMonth, $targetYear, $startDate, $endDate);
        $insCircle->execute();
        $targetCircleId = $conn->insert_id;
        $insCircle->close();
    }

    // 4. Fetch Active Employees
    $empRes = $conn->query("SELECT id FROM employees WHERE status = 'active'");
    if (!$empRes) {
        return false;
    }

    // Statement to update/insert target circle balances
    $upsertStmt = $conn->prepare("
        INSERT INTO leave_balances 
            (employee_id, payroll_circle_id, leave_type_id, year, allocated_days, used_days, carry_forward, remaining_days)
        VALUES (?, ?, ?, ?, 0.00, 0.00, ?, ?)
        ON DUPLICATE KEY UPDATE 
            carry_forward = VALUES(carry_forward),
            remaining_days = allocated_days + VALUES(carry_forward) - used_days
    ");

    while ($emp = $empRes->fetch_assoc()) {
        $empId = intval($emp['id']);

        // Fetch remaining balances from source payroll circle
        $balStmt = $conn->prepare("
            SELECT leave_type_id, allocated_days, used_days, carry_forward, remaining_days 
            FROM leave_balances 
            WHERE employee_id = ? AND payroll_circle_id = ?
        ");
        $balStmt->bind_param("ii", $empId, $sourceCircleId);
        $balStmt->execute();
        $bRes = $balStmt->get_result();

        while ($bRow = $bRes->fetch_assoc()) {
            $leaveTypeId = intval($bRow['leave_type_id']);
            
            // Calculate Unused Balance
            $unused = isset($bRow['remaining_days']) 
                ? floatval($bRow['remaining_days']) 
                : (floatval($bRow['allocated_days']) + floatval($bRow['carry_forward']) - floatval($bRow['used_days']));

            if ($unused > 0) {
                // Apply optional cap
                $carryAmount = ($maxCap !== null) ? min($unused, floatval($maxCap)) : $unused;
                $initialRemaining = $carryAmount;

                // Push calculated carry_forward into target payroll circle balance
                $upsertStmt->bind_param("iiiidd", $empId, $targetCircleId, $leaveTypeId, $targetYear, $carryAmount, $initialRemaining);
                $upsertStmt->execute();
            }
        }
        $balStmt->close();
    }
    $upsertStmt->close();
    return true;
}

// Handle Actions
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
    
    // Close Active Payroll Circle & Carry Forward Unused Leave
    if ($_POST['action'] === 'close_cycle_and_rollover') {
        $cycleId = intval($_POST['cycle_id'] ?? 0);
        $maxCap  = !empty($_POST['max_cap']) ? floatval($_POST['max_cap']) : null;

        try {
            // Mark circle as completed
            $uStmt = $conn->prepare("UPDATE payroll_circles SET status = 'completed', updated_at = NOW() WHERE id = ?");
            $uStmt->bind_param("i", $cycleId);
            $uStmt->execute();
            $uStmt->close();

            // Execute carryforward logic to next payroll circle
            executeMonthlyLeaveCarryForward($conn, $cycleId, $maxCap);

            header("Location: leave_rollover.php?msg=" . urlencode("Monthly Payroll Circle closed. Leave balances carried forward to next cycle successfully."));
            exit;
        } catch (mysqli_sql_exception $e) {
            header("Location: leave_rollover.php?err=" . urlencode("SQL Error: " . $e->getMessage()));
            exit;
        }
    }
}

// Fetch Payroll Circles List Safely
$payrollCircles = [];
try {
    $cRes = $conn->query("SELECT * FROM payroll_circles ORDER BY start_date DESC");
    if ($cRes) {
        while ($cRow = $cRes->fetch_assoc()) {
            $payrollCircles[] = $cRow;
        }
    }
} catch (mysqli_sql_exception $e) {
    $tableErrorMsg = $e->getMessage();
}