<?php
/**
 * Enterprise HRM ERP System - Calculate Payroll
 * Server-side calculations only
 */

require_once __DIR__ . '/../../includes/init.php';
requireLogin();

$pageTitle = 'Calculate Payroll';
$currentModule = 'payroll';

$siteId = getCurrentSiteId();
$periodId = isset($_GET['period_id']) ? (int)$_GET['period_id'] : 0;

if ($periodId <= 0) {
    redirect(BASE_URL . '/modules/payroll/list.php', 'Invalid payroll period.', 'error');
}

// Get payroll period
try {
    $db = getDB();
    $stmt = $db->prepare("SELECT * FROM payroll_periods WHERE period_id = ? AND site_id = ?");
    $stmt->execute([$periodId, $siteId]);
    $period = $stmt->fetch();
    
    if (!$period) {
        redirect(BASE_URL . '/modules/payroll/list.php', 'Payroll period not found.', 'error');
    }
    
    if (in_array($period['period_status'], ['locked', 'paid'])) {
        redirect(BASE_URL . '/modules/payroll/register.php?period_id=' . $periodId, 'This payroll period is locked.', 'error');
    }
    
} catch (Exception $e) {
    error_log("Error loading period: " . $e->getMessage());
    redirect(BASE_URL . '/modules/payroll/list.php', 'Error loading payroll period.', 'error');
}

$errors = [];
$success = false;
$calculated = 0;

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['calculate'])) {
    try {
        $db = getDB();
        $db->beginTransaction();
        
        // Get all active employees for this site
        $stmt = $db->prepare("
            SELECT employee_id FROM employees
            WHERE site_id = ? AND employment_status = 'active'
        ");
        $stmt->execute([$siteId]);
        $employees = $stmt->fetchAll(PDO::FETCH_COLUMN);
        
        $calculated = 0;
        
        foreach ($employees as $employeeId) {
            // Get employee salary structure
            $stmt = $db->prepare("
                SELECT sc.component_code, sc.component_type, sc.calculation_type, sc.calculation_value,
                       ess.amount as base_amount
                FROM employee_salary_structure ess
                INNER JOIN salary_components sc ON ess.component_id = sc.component_id
                WHERE ess.employee_id = ? AND ess.structure_status = 'active'
                AND sc.component_status = 'active'
            ");
            $stmt->execute([$employeeId]);
            $salaryStructure = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            if (empty($salaryStructure)) {
                continue; // Skip employees without salary structure
            }
            
            // Get attendance summary for the period
            $stmt = $db->prepare("
                SELECT 
                    COUNT(DISTINCT attendance_date) as working_days,
                    SUM(CASE WHEN attendance_status = 'present' THEN 1 ELSE 0 END) as present_days,
                    SUM(CASE WHEN attendance_status = 'absent' THEN 1 ELSE 0 END) as absent_days
                FROM attendance
                WHERE employee_id = ? AND site_id = ?
                AND attendance_date BETWEEN ? AND ?
            ");
            $stmt->execute([$employeeId, $siteId, $period['start_date'], $period['end_date']]);
            $attendance = $stmt->fetch();
            
            // Get overtime hours for the period
            $stmt = $db->prepare("
                SELECT SUM(overtime_hours) as total_ot_hours, SUM(overtime_amount) as total_ot_amount
                FROM overtime_records
                WHERE employee_id = ? AND site_id = ?
                AND overtime_date BETWEEN ? AND ?
            ");
            $stmt->execute([$employeeId, $siteId, $period['start_date'], $period['end_date']]);
            $overtime = $stmt->fetch();
            
            // Get leave days (LWP - Leave Without Pay)
            $stmt = $db->prepare("
                SELECT SUM(total_days) as lwp_days
                FROM leave_applications
                WHERE employee_id = ? AND site_id = ?
                AND application_status = 'approved'
                AND leave_type_id IN (SELECT leave_type_id FROM leave_types WHERE leave_type_code = 'LWP')
                AND start_date <= ? AND end_date >= ?
            ");
            $stmt->execute([$employeeId, $siteId, $period['end_date'], $period['start_date']]);
            $lwp = $stmt->fetch();
            $lwpDays = $lwp ? (float)$lwp['lwp_days'] : 0;
            
            // Calculate working days (considering LWP)
            $workingDays = (float)$attendance['working_days'];
            $presentDays = (float)$attendance['present_days'];
            $absentDays = (float)$attendance['absent_days'];
            $payDays = $presentDays; // Pay days = present days (LWP already deducted from attendance)
            
            // Calculate earnings and deductions
            $earnings = [];
            $deductions = [];
            $basicSalary = 0;
            
            foreach ($salaryStructure as $component) {
                $amount = (float)$component['base_amount'];
                
                if ($component['calculation_type'] === 'percentage' && $component['component_code'] === 'BASIC') {
                    // Basic is usually fixed, but if percentage, calculate from CTC
                    // This is simplified - adjust based on your business logic
                }
                
                // Pro-rate based on pay days if needed
                if ($component['component_type'] === 'earning' && $workingDays > 0) {
                    $proratedAmount = ($amount / $workingDays) * $payDays;
                } else {
                    $proratedAmount = $amount;
                }
                
                if ($component['component_code'] === 'BASIC') {
                    $basicSalary = $proratedAmount;
                }
                
                if ($component['component_type'] === 'earning') {
                    $earnings[$component['component_id']] = $proratedAmount;
                } else {
                    // Deductions (PF, ESIC, TDS) - calculate based on rules
                    if ($component['calculation_type'] === 'percentage') {
                        $deductionAmount = ($basicSalary * $component['calculation_value']) / 100;
                    } else {
                        $deductionAmount = $proratedAmount;
                    }
                    $deductions[$component['component_id']] = $deductionAmount;
                }
            }
            
            // Add overtime to earnings
            if ($overtime && $overtime['total_ot_amount'] > 0) {
                // Find or create OT component
                $stmt = $db->prepare("SELECT component_id FROM salary_components WHERE site_id = ? AND component_code = 'OT' LIMIT 1");
                $stmt->execute([$siteId]);
                $otComponent = $stmt->fetch();
                if ($otComponent) {
                    $earnings[$otComponent['component_id']] = (float)$overtime['total_ot_amount'];
                }
            }
            
            $totalEarnings = array_sum($earnings);
            $totalDeductions = array_sum($deductions);
            $taxableIncome = $totalEarnings - $totalDeductions;
            
            // Calculate tax (simplified - adjust based on your tax rules)
            $taxAmount = 0;
            $taxRate = getSetting('PAYROLL_TAX_RATE', 0);
            if ($taxRate > 0) {
                $taxAmount = ($taxableIncome * $taxRate) / 100;
            }
            
            $netSalary = $totalEarnings - $totalDeductions - $taxAmount;
            
            // Insert or update payroll record
            $stmt = $db->prepare("
                INSERT INTO payroll_records (
                    site_id, period_id, employee_id,
                    working_days, present_days, absent_days, overtime_hours,
                    gross_salary, total_earnings, total_deductions,
                    taxable_income, tax_amount, net_salary,
                    payroll_status, calculated_at, created_by
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'calculated', NOW(), ?)
                ON DUPLICATE KEY UPDATE
                    working_days = VALUES(working_days),
                    present_days = VALUES(present_days),
                    absent_days = VALUES(absent_days),
                    overtime_hours = VALUES(overtime_hours),
                    gross_salary = VALUES(gross_salary),
                    total_earnings = VALUES(total_earnings),
                    total_deductions = VALUES(total_deductions),
                    taxable_income = VALUES(taxable_income),
                    tax_amount = VALUES(tax_amount),
                    net_salary = VALUES(net_salary),
                    payroll_status = 'calculated',
                    calculated_at = NOW(),
                    updated_by = VALUES(created_by),
                    updated_at = NOW()
            ");
            $stmt->execute([
                $siteId, $periodId, $employeeId,
                $workingDays, $presentDays, $absentDays, (float)($overtime['total_ot_hours'] ?? 0),
                $basicSalary, $totalEarnings, $totalDeductions,
                $taxableIncome, $taxAmount, $netSalary,
                getCurrentUserId()
            ]);
            
            $payrollId = $db->lastInsertId();
            if (!$payrollId) {
                // Get existing payroll_id
                $stmt = $db->prepare("SELECT payroll_id FROM payroll_records WHERE period_id = ? AND employee_id = ?");
                $stmt->execute([$periodId, $employeeId]);
                $payrollId = $stmt->fetchColumn();
            }
            
            // Delete existing payroll details
            $stmt = $db->prepare("DELETE FROM payroll_details WHERE payroll_id = ?");
            $stmt->execute([$payrollId]);
            
            // Insert earnings
            foreach ($earnings as $componentId => $amount) {
                if ($amount > 0) {
                    $stmt = $db->prepare("INSERT INTO payroll_details (payroll_id, component_id, amount) VALUES (?, ?, ?)");
                    $stmt->execute([$payrollId, $componentId, $amount]);
                }
            }
            
            // Insert deductions
            foreach ($deductions as $componentId => $amount) {
                if ($amount > 0) {
                    $stmt = $db->prepare("INSERT INTO payroll_details (payroll_id, component_id, amount) VALUES (?, ?, ?)");
                    $stmt->execute([$payrollId, $componentId, $amount]);
                }
            }
            
            $calculated++;
        }
        
        // Update period status
        $stmt = $db->prepare("UPDATE payroll_periods SET period_status = 'processing', updated_by = ?, updated_at = NOW() WHERE period_id = ?");
        $stmt->execute([getCurrentUserId(), $periodId]);
        
        $db->commit();
        
        $success = true;
        logAudit('CALCULATE', 'payroll_periods', $periodId);
        
    } catch (Exception $e) {
        if ($db->inTransaction()) {
            $db->rollBack();
        }
        error_log("Error calculating payroll: " . $e->getMessage());
        $errors[] = 'An error occurred while calculating payroll. Please try again.';
    }
}

include __DIR__ . '/../../includes/header.php';
?>

<div class="card">
    <div class="card-header">
        <h2 class="card-title">Calculate Payroll</h2>
        <a href="<?php echo BASE_URL; ?>/modules/payroll/register.php?period_id=<?php echo $periodId; ?>" 
           class="btn btn-secondary">Back to Register</a>
    </div>
    
    <?php if ($success): ?>
    <div class="alert alert-success" style="margin-top: 20px;">
        Payroll calculated successfully for <?php echo number_format($calculated); ?> employees.
        <a href="<?php echo BASE_URL; ?>/modules/payroll/register.php?period_id=<?php echo $periodId; ?>" 
           class="btn btn-sm btn-primary" style="margin-left: 10px;">View Register</a>
    </div>
    <?php endif; ?>
    
    <?php if (!empty($errors)): ?>
    <div class="alert alert-error" style="margin-top: 20px;">
        <ul style="margin: 0; padding-left: 20px;">
            <?php foreach ($errors as $error): ?>
            <li><?php echo htmlspecialchars($error); ?></li>
            <?php endforeach; ?>
        </ul>
    </div>
    <?php endif; ?>
    
    <div style="margin-top: 20px; padding: 20px; background: #f9fafb; border-radius: 8px;">
        <h3 style="margin-bottom: 15px;">Payroll Period: <?php echo htmlspecialchars($period['period_name']); ?></h3>
        <p><strong>Period:</strong> <?php echo formatDate($period['start_date']); ?> to <?php echo formatDate($period['end_date']); ?></p>
        <p><strong>Pay Date:</strong> <?php echo formatDate($period['pay_date']); ?></p>
        <p><strong>Status:</strong> <span class="status-badge status-<?php echo $period['period_status']; ?>"><?php echo ucfirst($period['period_status']); ?></span></p>
        
        <div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid var(--border-color);">
            <p style="margin-bottom: 15px;">This will calculate payroll for all active employees based on:</p>
            <ul style="margin-left: 20px; margin-bottom: 20px;">
                <li>Attendance records for the period</li>
                <li>Overtime hours and amounts</li>
                <li>Leave applications (LWP deductions)</li>
                <li>Employee salary structure</li>
                <li>Salary components (earnings and deductions)</li>
            </ul>
            
            <form method="POST">
                <button type="submit" name="calculate" class="btn btn-primary btn-lg" 
                        onclick="return confirm('Are you sure you want to calculate payroll for this period? This may take a few moments.');">
                    Calculate Payroll
                </button>
            </form>
        </div>
    </div>
</div>

<?php include __DIR__ . '/../../includes/footer.php'; ?>

