<?php
/** Payroll — AJAX API. Access: admin / accountant / headteacher / director. */
if (session_status() === PHP_SESSION_NONE) session_start();
header('Content-Type: application/json');

require_once __DIR__ . '/../../config.php';
if (!isset($_SESSION['user_id'])) { http_response_code(401); echo json_encode(['success' => false, 'message' => 'Not signed in.']); exit; }
requireModule('payroll', true);
require_once __DIR__ . '/../../includes/payroll_lib.php';

$role = $_SESSION['role'] ?? '';
if (!payroll_can_manage($role)) { http_response_code(403); echo json_encode(['success' => false, 'message' => 'Not permitted.']); exit; }

$conn = getDBConnection();
payroll_ensure_tables($conn);
$uid = (int) $_SESSION['user_id'];
$action = $_POST['action'] ?? $_GET['action'] ?? '';
function pr_out($p){ echo json_encode($p); exit; }

switch ($action) {

    // Staff list joined with their pay setup.
    case 'staff_pay_list': {
        $rows = [];
        $res = $conn->query("SELECT s.id, s.staff_id, s.full_name, s.bank_name, s.bank_account, s.ssnit_number,
                                    p.basic_salary, p.transport_allowance, p.housing_allowance, p.other_allowance,
                                    p.other_deductions, p.tax_relief, p.ssnit_exempt
                             FROM staff s
                             LEFT JOIN payroll_staff_pay p ON p.staff_id = s.id
                             ORDER BY s.full_name");
        while ($res && $r = $res->fetch_assoc()) {
            $pay = [
                'basic_salary' => $r['basic_salary'] ?? 0,
                'transport_allowance' => $r['transport_allowance'] ?? 0,
                'housing_allowance' => $r['housing_allowance'] ?? 0,
                'other_allowance' => $r['other_allowance'] ?? 0,
                'other_deductions' => $r['other_deductions'] ?? 0,
                'tax_relief' => $r['tax_relief'] ?? 0,
                'ssnit_exempt' => $r['ssnit_exempt'] ?? 0,
            ];
            $r['computed'] = payroll_compute($pay);
            $rows[] = $r;
        }
        pr_out(['success' => true, 'data' => $rows]);
    }

    case 'save_pay': {
        $sid = (int) ($_POST['staff_id'] ?? 0);
        if (!$sid) pr_out(['success' => false, 'message' => 'No staff selected.']);
        $basic = (float) ($_POST['basic_salary'] ?? 0);
        $tr    = (float) ($_POST['transport_allowance'] ?? 0);
        $ho    = (float) ($_POST['housing_allowance'] ?? 0);
        $oa    = (float) ($_POST['other_allowance'] ?? 0);
        $od    = (float) ($_POST['other_deductions'] ?? 0);
        $relief= (float) ($_POST['tax_relief'] ?? 0);
        $exempt= !empty($_POST['ssnit_exempt']) ? 1 : 0;
        $stmt = $conn->prepare("INSERT INTO payroll_staff_pay
            (staff_id, basic_salary, transport_allowance, housing_allowance, other_allowance, other_deductions, tax_relief, ssnit_exempt)
            VALUES (?,?,?,?,?,?,?,?)
            ON DUPLICATE KEY UPDATE basic_salary=VALUES(basic_salary), transport_allowance=VALUES(transport_allowance),
             housing_allowance=VALUES(housing_allowance), other_allowance=VALUES(other_allowance),
             other_deductions=VALUES(other_deductions), tax_relief=VALUES(tax_relief), ssnit_exempt=VALUES(ssnit_exempt)");
        $stmt->bind_param('iddddddi', $sid, $basic, $tr, $ho, $oa, $od, $relief, $exempt);
        $stmt->execute(); $stmt->close();
        pr_out(['success' => true, 'message' => 'Pay details saved.', 'computed' => payroll_compute([
            'basic_salary' => $basic, 'transport_allowance' => $tr, 'housing_allowance' => $ho,
            'other_allowance' => $oa, 'other_deductions' => $od, 'tax_relief' => $relief, 'ssnit_exempt' => $exempt,
        ])]);
    }

    case 'runs_list': {
        $rows = [];
        $res = $conn->query("SELECT r.*,
            (SELECT COUNT(*) FROM payroll_items i WHERE i.run_id=r.id) staff_count,
            (SELECT COALESCE(SUM(net),0) FROM payroll_items i WHERE i.run_id=r.id) net_total
            FROM payroll_runs r ORDER BY r.period DESC");
        while ($res && $r = $res->fetch_assoc()) $rows[] = $r;
        pr_out(['success' => true, 'data' => $rows]);
    }

    // Create a run for a period and snapshot every active staff member's pay.
    case 'create_run': {
        $period = trim($_POST['period'] ?? '');
        if (!preg_match('/^\d{4}-\d{2}$/', $period)) pr_out(['success' => false, 'message' => 'Period must be YYYY-MM.']);
        $note = trim($_POST['note'] ?? '') ?: null;

        $exists = $conn->prepare("SELECT id FROM payroll_runs WHERE period=?");
        $exists->bind_param('s', $period); $exists->execute();
        if ($exists->get_result()->fetch_assoc()) { $exists->close(); pr_out(['success' => false, 'message' => 'A run for that period already exists.']); }
        $exists->close();

        $stmt = $conn->prepare("INSERT INTO payroll_runs (period, note, created_by) VALUES (?,?,?)");
        $stmt->bind_param('ssi', $period, $note, $uid); $stmt->execute();
        $runId = $stmt->insert_id; $stmt->close();

        $res = $conn->query("SELECT s.id, s.full_name, s.bank_name, s.bank_account, s.ssnit_number,
                                    p.basic_salary, p.transport_allowance, p.housing_allowance, p.other_allowance,
                                    p.other_deductions, p.tax_relief, p.ssnit_exempt
                             FROM staff s JOIN payroll_staff_pay p ON p.staff_id = s.id
                             WHERE p.active = 1 AND p.basic_salary > 0");
        $count = 0;
        while ($res && $r = $res->fetch_assoc()) {
            $c = payroll_compute($r);
            $ins = $conn->prepare("INSERT INTO payroll_items
                (run_id, staff_id, staff_name, basic, allowances, gross, ssnit_employee, ssnit_employer, taxable, paye, other_deductions, net, bank_name, bank_account, ssnit_number)
                VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
            $ins->bind_param('iisdddddddddsss',
                $runId, $r['id'], $r['full_name'], $c['basic'], $c['allowances'], $c['gross'],
                $c['ssnit_employee'], $c['ssnit_employer'], $c['taxable'], $c['paye'], $c['other_deductions'], $c['net'],
                $r['bank_name'], $r['bank_account'], $r['ssnit_number']);
            $ins->execute(); $ins->close();
            $count++;
        }
        pr_out(['success' => true, 'message' => "Payroll run created for {$period} — {$count} staff.", 'run_id' => $runId]);
    }

    case 'get_run': {
        $id = (int) ($_GET['id'] ?? $_POST['id'] ?? 0);
        $stmt = $conn->prepare("SELECT * FROM payroll_runs WHERE id=?");
        $stmt->bind_param('i', $id); $stmt->execute();
        $run = $stmt->get_result()->fetch_assoc(); $stmt->close();
        if (!$run) pr_out(['success' => false, 'message' => 'Run not found.']);
        $items = [];
        $res = $conn->query("SELECT * FROM payroll_items WHERE run_id=$id ORDER BY staff_name");
        while ($res && $r = $res->fetch_assoc()) $items[] = $r;
        $tot = ['gross' => 0, 'ssnit_employee' => 0, 'ssnit_employer' => 0, 'paye' => 0, 'net' => 0];
        foreach ($items as $it) foreach ($tot as $k => $_) $tot[$k] += (float) $it[$k];
        pr_out(['success' => true, 'run' => $run, 'items' => $items, 'totals' => $tot]);
    }

    case 'finalize_run': {
        $id = (int) ($_POST['id'] ?? 0);
        $conn->query("UPDATE payroll_runs SET status='finalized', finalized_at=NOW() WHERE id=$id AND status='draft'");
        pr_out(['success' => true, 'message' => 'Run finalized. It is now locked.']);
    }

    case 'delete_run': {
        $id = (int) ($_POST['id'] ?? 0);
        $r = $conn->query("SELECT status FROM payroll_runs WHERE id=$id")->fetch_assoc();
        if (!$r) pr_out(['success' => false, 'message' => 'Run not found.']);
        if ($r['status'] === 'finalized') pr_out(['success' => false, 'message' => 'Finalized runs cannot be deleted.']);
        $conn->query("DELETE FROM payroll_items WHERE run_id=$id");
        $conn->query("DELETE FROM payroll_runs WHERE id=$id");
        pr_out(['success' => true, 'message' => 'Draft run deleted.']);
    }

    default:
        pr_out(['success' => false, 'message' => 'Unknown action.']);
}
