<?php

namespace App\Controllers;

use App\Core\Controller;
use App\Helpers\Auth;
use App\Helpers\Csrf;
use App\Helpers\Exporter;
use App\Helpers\SessionHelper;
use App\Helpers\SettingHelper;
use App\Models\AdvanceSalary;
use App\Models\Claim;
use App\Models\LeaveRequest;
use App\Models\Role;
use App\Models\StaffProfile;
use App\Models\Setting;
use App\Models\User;
use PDO;

class AdminController extends Controller
{
    private PDO $pdo;  // Declare property manually

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo; // Assign manually (PHP 7.4 style)
    }

    public function requests(): void
    {
        Auth::requireRole(['admin']);

        $status = $_GET['status'] ?? 'approved';
        $search = $_GET['search'] ?? null;
        $month = $_GET['month'] ?? null;
        $year = $_GET['year'] ?? null;
        $staffId = isset($_GET['staff_id']) ? (int) $_GET['staff_id'] : 0;
        $sort = $_GET['sort'] ?? 'date';
        $direction = $_GET['direction'] ?? 'DESC';
        $locationFilter = trim($_GET['location'] ?? '');
        $locationUserIds = [];
        if ($locationFilter !== '') {
            $profileModel = new StaffProfile($this->pdo);
            $locationUserIds = $profileModel->userIdsByLocation($locationFilter);
        }

        $advanceFilters = array_filter([
            'status' => $status,
            'search' => $search,
            'user_id' => $staffId ?: null,
            'sort' => $sort,
            'direction' => $direction,
            'user_ids' => $locationUserIds,
        ]);
        $leaveFilters = array_filter([
            'status' => $status,
            'user_id' => $staffId ?: null,
            'month' => $month,
            'year' => $year,
            'search' => $search,
            'sort' => $sort,
            'direction' => $direction,
            'user_ids' => $locationUserIds,
        ]);
        $claimFilters = array_filter([
            'status' => $status,
            'search' => $search,
            'user_id' => $staffId ?: null,
            'sort' => $sort,
            'direction' => $direction,
            'user_ids' => $locationUserIds,
        ]);

        $limit = 10;
        $pageAdv = max(1, (int) ($_GET['page_adv'] ?? 1));
        $pageLeave = max(1, (int) ($_GET['page_leave'] ?? 1));
        $pageClaim = max(1, (int) ($_GET['page_claim'] ?? 1));

        $advModel = new AdvanceSalary($this->pdo);
        $leaveModel = new LeaveRequest($this->pdo);
        $claimModel = new Claim($this->pdo);

        $advance = $advModel->paginate($advanceFilters, $limit, ($pageAdv - 1) * $limit);
        $leave = $leaveModel->filter($leaveFilters, $limit, ($pageLeave - 1) * $limit);
        $claims = $claimModel->paginate($claimFilters, $limit, ($pageClaim - 1) * $limit);

        $pagination = [
            'advance' => [
                'page' => $pageAdv,
                'total' => $advModel->count($advanceFilters),
                'limit' => $limit,
            ],
            'leave' => [
                'page' => $pageLeave,
                'total' => $leaveModel->count($leaveFilters),
                'limit' => $limit,
            ],
            'claim' => [
                'page' => $pageClaim,
                'total' => $claimModel->count($claimFilters),
                'limit' => $limit,
            ],
        ];

        $query = $_GET;
        $query['route'] = 'admin/requests';
        $staffList = array_values(array_filter(
            (new User($this->pdo))->all(),
            fn ($user) => $user['role'] === 'staff'
        ));

        $summary = $this->payrollSummary(
			$status,
			$staffId ?: null,
			($month !== null && $month !== '' ? (int)$month : null),
			($year !== null && $year !== '' ? (int)$year : null)
		);

        $locationOptions = SettingHelper::get()['locations'] ?? [];

        $this->view('admin/requests', [
            'advance' => $advance,
            'leave' => $leave,
            'claims' => $claims,
            'summary' => $summary,
            'filters' => [
                'status' => $status,
                'search' => $search,
                'month' => $month,
                'year' => $year,
                'staff_id' => $staffId,
                'sort' => $sort,
                'direction' => $direction,
                'location' => $locationFilter,
            ],
            'pagination' => $pagination,
            'query' => $query,
            'staffList' => $staffList,
            'locations' => $locationOptions,
            'csrf' => Csrf::field(),
            'message' => SessionHelper::flash('message'),
            'error' => SessionHelper::flash('error'),
        ]);
    }

    public function export(): void
    {
        Auth::requireRole(['admin']);
        $type = $_GET['type'] ?? 'advance';
        $format = $_GET['format'] ?? 'csv';
        $status = $_GET['status'] ?? 'approved';
        $staffId = isset($_GET['staff_id']) ? (int) $_GET['staff_id'] : 0;
        $month = isset($_GET['month']) && $_GET['month'] !== '' ? (int) $_GET['month'] : null;
        $year = isset($_GET['year']) && $_GET['year'] !== '' ? (int) $_GET['year'] : null;
        $location = trim($_GET['location'] ?? '');
        $locationUserIds = [];
        if ($location !== '') {
            $profileModel = new StaffProfile($this->pdo);
            $locationUserIds = $profileModel->userIdsByLocation($location);
        }

        // Default headers (akan disesuaikan mengikut jenis & filter)
        $headers = [];
        $rows = [];
        switch ($type) {
            case 'advance':
                // Jika semua staff, paparkan lajur nama; jika ditapis staff tertentu, nama akan dipaparkan di header sahaja
                $headers = $staffId ? ['ID', 'Status', 'Amount', 'Updated'] : ['ID', 'Nama', 'Status', 'Amount', 'Updated'];
                $data = (new AdvanceSalary($this->pdo))->paginate([
                    'status' => $status,
                    'user_id' => $staffId ?: null,
                    'user_ids' => $locationUserIds,
                ], 500, 0);
                foreach ($data as $row) {
                    if ($staffId) {
                        $rows[] = [$row['id'], $row['status'], $row['jumlah'], $row['updated_at']];
                    } else {
                    $rows[] = [$row['id'], $row['nama'], $row['status'], $row['jumlah'], $row['updated_at']];
                    }
                }
                break;
            case 'leave':
                $headers = $staffId
                    ? ['ID', 'Tempat', 'Jumlah Hari', 'Status', 'Tarikh Mula']
                    : ['ID', 'Nama', 'Tempat', 'Jumlah Hari', 'Status', 'Tarikh Mula'];
                $data = (new LeaveRequest($this->pdo))->filter([
                    'status' => $status,
                    'user_id' => $staffId ?: null,
                    'month' => $month,
                    'year' => $year,
                    'user_ids' => $locationUserIds,
                ], 500, 0);
                foreach ($data as $row) {
                    if ($staffId) {
                        $rows[] = [$row['id'], $row['tempat_bekerja'], $row['jumlah_hari'], $row['status'], $row['tarikh_mula']];
                    } else {
                    $rows[] = [$row['id'], $row['nama'], $row['tempat_bekerja'], $row['jumlah_hari'], $row['status'], $row['tarikh_mula']];
                    }
                }
                break;
            case 'claim':
                $headers = $staffId ? ['ID', 'Status', 'Amount', 'Updated'] : ['ID', 'Nama', 'Status', 'Amount', 'Updated'];
                $data = (new Claim($this->pdo))->paginate([
                    'status' => $status,
                    'user_id' => $staffId ?: null,
                    'user_ids' => $locationUserIds,
                ], 500, 0);
                foreach ($data as $row) {
                    if ($staffId) {
                        $rows[] = [$row['id'], $row['status'], $row['amount'], $row['updated_at']];
                    } else {
                    $rows[] = [$row['id'], $row['nama_staff'], $row['status'], $row['amount'], $row['updated_at']];
                    }
                }
                break;
        }

        if ($format === 'pdf') {
            $config = require __DIR__ . '/../../config/config.php';
            $appName = htmlspecialchars($config['app_name'] ?? 'Mutiara Group Portal');
            $branding = SettingHelper::get();

            $logoUrl = null;
            if (!empty($branding['logo_path'])) {
                $baseUrl = $config['base_url'] ?? '';
                $logoUrl = $baseUrl . '/uploads/branding/' . ltrim($branding['logo_path'], '/');
            }

            $title = ucfirst($type) . ' Report';

            $filterParts = [];
            if ($status) {
                $filterParts[] = 'Status: ' . ucfirst($status);
            }
            $staffLabel = 'Semua Staff';
            if ($staffId) {
                $userModel = new User($this->pdo);
                $staff = $userModel->find($staffId);
                if ($staff) {
                    $staffLabel = $staff['name'] . ' (' . $staff['login_id'] . ')';
                } else {
                    $staffLabel = 'Staff ID: ' . $staffId;
                }
                $filterParts[] = 'Staff: ' . $staffLabel;
            }

            if ($month) {
                $filterParts[] = 'Month: ' . $month;
            }
            if ($year) {
                $filterParts[] = 'Year: ' . $year;
            }
            if ($location) {
                $filterParts[] = 'Lokasi: ' . $location;
            }
            $filterText = $filterParts ? implode(' | ', $filterParts) : 'All records';

            $html = '<!doctype html><html><head><meta charset="utf-8"><style>
                body{font-family:system-ui,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;font-size:12px;color:#111827;margin:0;padding:24px;background:#f3f4f6;}
                .report-card{background:#ffffff;border-radius:12px;padding:20px 24px;box-shadow:0 10px 30px rgba(15,23,42,0.15);border:1px solid #e5e7eb;}
                .report-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:16px;border-bottom:1px solid #e5e7eb;padding-bottom:10px;gap:16px;}
                .report-logo img{max-height:48px;}
                .report-title{font-size:18px;font-weight:700;color:#111827;margin:0;}
                .report-meta{font-size:11px;color:#6b7280;text-align:right;}
                .badge{display:inline-block;padding:2px 8px;border-radius:999px;background:#e5e7eb;font-size:10px;color:#374151;margin-left:4px;}
                .filters{font-size:11px;color:#4b5563;margin-bottom:12px;}
                table{width:100%;border-collapse:collapse;margin-top:8px;font-size:11px;}
                thead th{background:#111827;color:#f9fafb;padding:6px 8px;text-align:left;border-bottom:1px solid #e5e7eb;}
                tbody td{padding:5px 8px;border-bottom:1px solid #e5e7eb;}
                tr:nth-child(even) td{background:#f9fafb;}
                .text-right{text-align:right;}
                .status-pill{display:inline-block;padding:2px 8px;border-radius:999px;font-size:10px;}
                .status-approved{background:#dcfce7;color:#166534;}
                .status-pending{background:#fef9c3;color:#854d0e;}
                .status-rejected{background:#fee2e2;color:#991b1b;}
                .footer{margin-top:16px;font-size:10px;color:#9ca3af;text-align:right;}
            </style></head><body>';

            $html .= '<div class="report-card">';
            $html .= '<div class="report-header">';

            if ($logoUrl) {
                $html .= '<div class="report-logo"><img src="' . htmlspecialchars($logoUrl) . '" alt="Logo"></div>';
            }

            $html .= '<div><div class="report-title">' . htmlspecialchars($title) . '</div>';
            $html .= '<div class="filters">' . htmlspecialchars($filterText) . '</div>';
            if ($staffLabel !== 'Semua Staff') {
                $html .= '<div class="filters">Staff: ' . htmlspecialchars($staffLabel) . '</div>';
            }
            $html .= '</div>';
            $html .= '<div class="report-meta">';
            $html .= '<div>' . $appName . '</div>';
            $html .= '<div>' . date('d M Y, H:i') . '</div>';
            $html .= '</div></div>';

            $html .= '<table><thead><tr>';
            foreach ($headers as $header) {
                $html .= '<th>' . htmlspecialchars($header) . '</th>';
            }
            $html .= '</tr></thead><tbody>';
            foreach ($rows as $row) {
                $html .= '<tr>';
                foreach ($row as $idx => $value) {
                    $cell = htmlspecialchars((string) $value);
                    if ($headers[$idx] === 'Status') {
                        $statusClass = 'status-' . strtolower($value);
                        $html .= '<td><span class="status-pill ' . $statusClass . '">' . ucfirst(strtolower($cell)) . '</span></td>';
                    } elseif (in_array($headers[$idx], ['Amount', 'Jumlah Hari'], true)) {
                        $html .= '<td class="text-right">' . $cell . '</td>';
                    } else {
                        $html .= '<td>' . $cell . '</td>';
                    }
                }
                $html .= '</tr>';
            }
            if (!$rows) {
                $html .= '<tr><td colspan="' . count($headers) . '">No data for selected filters.</td></tr>';
            }
            $html .= '</tbody></table>';

            $html .= '<div class="footer">Generated by ' . $appName . '</div>';
            $html .= '</div></body></html>';

            Exporter::pdf($type . '_summary', $html);
        }

        Exporter::csv($type . '_summary', $headers, $rows);
    }

    public function users(): void
    {
        Auth::requireRole(['admin']);

        $userModel = new User($this->pdo);
        $roleModel = new Role($this->pdo);

        $users = $userModel->all();
        $grouped = [
            'admin' => [],
            'approver' => [],
            'staff' => [],
            'others' => [],
        ];

        foreach ($users as $user) {
            $roleKey = strtolower($user['role']);
            if (!array_key_exists($roleKey, $grouped)) {
                $roleKey = 'others';
            }
            $grouped[$roleKey][] = $user;
        }

        $this->view('admin/users', [
            'usersByRole' => $grouped,
            'roles' => $roleModel->all(),
            'csrf' => Csrf::field(),
            'message' => SessionHelper::flash('message'),
            'error' => SessionHelper::flash('error'),
        ]);
    }

    public function employees(): void
    {
        Auth::requireRole(['admin']);

        $locationFilter = trim($_GET['location'] ?? '');
        $staffProfiles = [];
        $totalEmployees = 0;
        $activeEmployees = 0;
        $loadError = null;
        $distinctLocations = [];
        $settingLocations = SettingHelper::get()['locations'] ?? [];

        try {
            $profileModel = new StaffProfile($this->pdo);
            $staffProfiles = $profileModel->allWithUser($locationFilter ?: null);
            $totalEmployees = $profileModel->countAll();
            $activeEmployees = $profileModel->countActive();
            $distinctLocations = !empty($settingLocations) ? $settingLocations : $profileModel->allLocations();
        } catch (\PDOException $e) {
            $loadError = 'Ralat memuatkan senarai pekerja. Pastikan jadual staff_profiles telah diwujudkan di pangkalan data.';
        }

        $this->view('admin/employees', [
            'staffProfiles' => $staffProfiles,
            'filterLocation' => $locationFilter,
            'locations' => $distinctLocations,
            'stats' => [
                'total' => $totalEmployees,
                'active' => $activeEmployees,
            ],
            'csrf' => Csrf::field(),
            'message' => SessionHelper::flash('message'),
            'error' => SessionHelper::flash('error') ?: $loadError,
        ]);
    }

    public function employeeCreate(): void
    {
        Auth::requireRole(['admin']);
        $setting = (new Setting($this->pdo))->get();
        $locations = $setting['locations'] ?? [];
        if (empty($locations)) {
            $locations = (new StaffProfile($this->pdo))->allLocations();
        }
        $this->view('admin/employee_create', [
            'csrf' => Csrf::field(),
            'message' => SessionHelper::flash('message'),
            'error' => SessionHelper::flash('error'),
            'locations' => $locations,
        ]);
    }

    public function storeEmployee(): void
    {
        Auth::requireRole(['admin']);

        if (!Csrf::validate($_POST['_token'] ?? null)) {
            SessionHelper::flash('error', 'Invalid CSRF token');
            header('Location: index.php?route=admin/employees');
            exit;
        }

        $name = trim($_POST['staff_name'] ?? '');
        $ic = preg_replace('/\D+/', '', $_POST['staff_ic'] ?? '');
        $email = filter_var($_POST['staff_email'] ?? '', FILTER_VALIDATE_EMAIL) ?: null;
        $address = trim($_POST['staff_address'] ?? '');
        $phone = trim($_POST['staff_phone'] ?? '');
        $hireDate = $_POST['staff_hire_date'] ?? null;
        $location = trim($_POST['staff_location'] ?? '');
        $bank = trim($_POST['staff_bank'] ?? '');
        $account = trim($_POST['staff_account'] ?? '');
        $allowedLeave = (int) ($_POST['staff_allowed_leave'] ?? 0);

        if ($name === '' || strlen($ic) !== 12) {
            SessionHelper::flash('error', 'Nama dan No. Kad Pengenalan (12 digit) diperlukan.');
            header('Location: index.php?route=admin/employees');
            exit;
        }

        // Cari role staff
        $roleStmt = $this->pdo->prepare("SELECT id FROM roles WHERE name = 'staff' LIMIT 1");
        $roleStmt->execute();
        $roleId = (int) $roleStmt->fetchColumn();

        if ($roleId <= 0) {
            SessionHelper::flash('error', 'Role staff tidak ditemui.');
            header('Location: index.php?route=admin/employees');
            exit;
        }

        // Daftar user baru: login_id = IC, password = IC
        $userModel = new User($this->pdo);
        try {
            $userModel->create([
                'name' => $name,
                'login_id' => $ic,
                'email' => $email,
                'password' => $ic,
                'role_id' => $roleId,
                'active' => 1,
            ]);
        } catch (\PDOException $e) {
            SessionHelper::flash('error', 'Gagal mendaftarkan pengguna: ' . $e->getMessage());
            header('Location: index.php?route=admin/employees');
            exit;
        }

        $userId = (int) $this->pdo->lastInsertId();
        if ($userId > 0) {
            $profile = new StaffProfile($this->pdo);
            $profile->create([
                'user_id' => $userId,
                'ic_no' => $ic,
                'address' => $address,
                'phone' => $phone,
                'hire_date' => $hireDate ?: null,
                'location' => $location,
                'bank_name' => $bank,
                'account_no' => $account,
                'allowed_leave' => $allowedLeave,
            ]);
        }

        SessionHelper::flash(
            'message',
            'Pekerja berjaya didaftarkan. ID Pengguna & Password: ' . $ic
        );
        header('Location: index.php?route=admin/employees/create');
    }

    public function updateEmployee(): void
    {
        Auth::requireRole(['admin']);

        if (!Csrf::validate($_POST['_token'] ?? null)) {
            SessionHelper::flash('error', 'Invalid CSRF token');
            header('Location: index.php?route=admin/employees');
            exit;
        }

        $userId = (int) ($_POST['user_id'] ?? 0);
        $name = trim($_POST['name'] ?? '');
        $email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL) ?: null;
        $address = trim($_POST['address'] ?? '');
        $phone = trim($_POST['phone'] ?? '');
        $hireDate = $_POST['hire_date'] ?? null;
        $location = trim($_POST['location'] ?? '');
        $bank = trim($_POST['bank_name'] ?? '');
        $account = trim($_POST['account_no'] ?? '');
        $allowedLeave = (int) ($_POST['allowed_leave'] ?? 0);

        if ($userId <= 0 || $name === '') {
            SessionHelper::flash('error', 'Nama pekerja wajib diisi.');
            header('Location: index.php?route=admin/employees');
            exit;
        }

        $userModel = new User($this->pdo);
        $userModel->update($userId, [
            'name' => $name,
            'email' => $email,
            'active' => 1,
        ]);

        $profileModel = new StaffProfile($this->pdo);
        $profileModel->updateByUserId($userId, [
            'address' => $address,
            'phone' => $phone,
            'hire_date' => $hireDate ?: null,
            'location' => $location,
            'bank_name' => $bank,
            'account_no' => $account,
            'allowed_leave' => $allowedLeave,
        ]);

        SessionHelper::flash('message', 'Maklumat pekerja dikemaskini.');
        header('Location: index.php?route=admin/employees');
    }

    public function deleteEmployee(): void
    {
        Auth::requireRole(['admin']);

        if (!Csrf::validate($_POST['_token'] ?? null)) {
            SessionHelper::flash('error', 'Invalid CSRF token');
            header('Location: index.php?route=admin/employees');
            exit;
        }

        $userId = (int) ($_POST['user_id'] ?? 0);
        if ($userId <= 0) {
            SessionHelper::flash('error', 'Pekerja tidak sah.');
            header('Location: index.php?route=admin/employees');
            exit;
        }

        $profileModel = new StaffProfile($this->pdo);
        $userModel = new User($this->pdo);

        try {
            // Padam profil dulu (FK)
            $profileModel->deleteByUserId($userId);
            // Kemudian padam user (staff)
            $userModel->delete($userId);
            SessionHelper::flash('message', 'Pekerja berjaya dipadam.');
        } catch (\PDOException $e) {
            SessionHelper::flash('error', 'Tidak boleh padam pekerja: ' . $e->getMessage());
        }

        header('Location: index.php?route=admin/employees');
    }

    public function storeUser(): void
    {
        Auth::requireRole(['admin']);

        if (!Csrf::validate($_POST['_token'] ?? null)) {
            SessionHelper::flash('error', 'Invalid CSRF token');
            header('Location: index.php?route=admin/users');
            exit;
        }

        $data = [
            'name' => trim($_POST['name'] ?? ''),
            'login_id' => trim($_POST['login_id'] ?? ''),
            'email' => filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL) ?: null,
            'password' => $_POST['password'] ?? '',
            'role_id' => (int) ($_POST['role_id'] ?? 0),
            'active' => isset($_POST['active']) ? 1 : 0,
        ];

        if (!$data['name'] || !$data['login_id'] || !$data['password'] || !$data['role_id']) {
            SessionHelper::flash('error', 'Sila lengkapkan nama, ID dan kata laluan.');
            header('Location: index.php?route=admin/users');
            exit;
        }

        if (!preg_match('/^\d{12}$/', $data['login_id'])) {
            SessionHelper::flash('error', 'ID mesti 12 digit angka.');
            header('Location: index.php?route=admin/users');
            exit;
        }

        (new User($this->pdo))->create($data);
        SessionHelper::flash('message', 'User created.');
        header('Location: index.php?route=admin/users');
    }

    public function resetPassword(): void
    {
        Auth::requireRole(['admin']);

        if (!Csrf::validate($_POST['_token'] ?? null)) {
            SessionHelper::flash('error', 'Invalid CSRF token');
            header('Location: index.php?route=admin/users');
            exit;
        }

        $userId = (int) ($_POST['user_id'] ?? 0);
        $password = $_POST['password'] ?? '';

        if ($userId <= 0 || strlen($password) < 6) {
            SessionHelper::flash('error', 'Password must be at least 6 characters.');
            header('Location: index.php?route=admin/users');
            exit;
        }

        (new User($this->pdo))->resetPassword($userId, $password);
        SessionHelper::flash('message', 'Password updated.');
        header('Location: index.php?route=admin/users');
    }

    public function updateUser(): void
    {
        Auth::requireRole(['admin']);

        if (!Csrf::validate($_POST['_token'] ?? null)) {
            SessionHelper::flash('error', 'Invalid CSRF token');
            header('Location: index.php?route=admin/users');
            exit;
        }

        $userId = (int) ($_POST['user_id'] ?? 0);
        $name = trim($_POST['name'] ?? '');
        $email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL) ?: null;
        $active = isset($_POST['active']) ? 1 : 0;

        if ($userId <= 0 || $name === '') {
            SessionHelper::flash('error', 'Nama wajib diisi.');
            header('Location: index.php?route=admin/users');
            exit;
        }

        (new User($this->pdo))->update($userId, [
            'name' => $name,
            'email' => $email,
            'active' => $active,
        ]);

        SessionHelper::flash('message', 'User updated.');
        header('Location: index.php?route=admin/users');
    }

    public function deleteUser(): void
    {
        Auth::requireRole(['admin']);

        if (!Csrf::validate($_POST['_token'] ?? null)) {
            SessionHelper::flash('error', 'Invalid CSRF token');
            header('Location: index.php?route=admin/users');
            exit;
        }

        $userId = (int) ($_POST['user_id'] ?? 0);
        $currentUser = SessionHelper::user();

        if ($userId <= 0) {
            SessionHelper::flash('error', 'Pengguna tidak sah.');
            header('Location: index.php?route=admin/users');
            exit;
        }

        if ($currentUser && (int) $currentUser['id'] === $userId) {
            SessionHelper::flash('error', 'Tidak boleh padam akaun sendiri.');
            header('Location: index.php?route=admin/users');
            exit;
        }

        try {
            (new User($this->pdo))->delete($userId);
            SessionHelper::flash('message', 'User deleted.');
        } catch (\PDOException $e) {
            SessionHelper::flash('error', 'Tidak boleh padam pengguna yang mempunyai rekod.');
        }
        header('Location: index.php?route=admin/users');
    }

    public function settings(): void
    {
        Auth::requireRole(['admin']);
        $settingModel = new Setting($this->pdo);

        $this->view('admin/settings', [
            'setting' => $settingModel->get(),
            'csrf' => Csrf::field(),
            'message' => SessionHelper::flash('message'),
            'error' => SessionHelper::flash('error'),
        ]);
    }

    public function updateSettings(): void
    {
        Auth::requireRole(['admin']);

        if (!Csrf::validate($_POST['_token'] ?? null)) {
            SessionHelper::flash('error', 'Invalid CSRF token');
            header('Location: index.php?route=admin/settings');
            exit;
        }

        $companyName = trim($_POST['company_name'] ?? '');
        $tagline = trim($_POST['tagline'] ?? '');
        $email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL) ?: null;
        $phone = trim($_POST['phone'] ?? '');
        $address = trim($_POST['address'] ?? '');
        $locationsRaw = trim($_POST['locations'] ?? '');
        $locations = array_filter(array_map('trim', explode("\n", $locationsRaw)));

        if ($companyName === '') {
            SessionHelper::flash('error', 'Nama syarikat diperlukan.');
            header('Location: index.php?route=admin/settings');
            exit;
        }

        $settingModel = new Setting($this->pdo);
        $current = $settingModel->get();

        $logoPath = $current['logo_path'] ?? null;
        $uploadDir = __DIR__ . '/../../public/uploads/branding';

        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0775, true);
        }

        $logoFile = $_FILES['logo'] ?? null;

        if ($logoFile && $logoFile['error'] !== UPLOAD_ERR_NO_FILE) {
            if ($logoFile['error'] !== UPLOAD_ERR_OK) {
                SessionHelper::flash('error', $this->uploadErrorMessage($logoFile['error']));
                header('Location: index.php?route=admin/settings');
                exit;
            }

            if (!is_writable($uploadDir)) {
                SessionHelper::flash('error', 'Folder uploads/branding tidak boleh ditulis. Sila semak permission.');
                header('Location: index.php?route=admin/settings');
                exit;
            }

            $ext = strtolower(pathinfo($logoFile['name'], PATHINFO_EXTENSION));
            $allowed = ['png', 'jpg', 'jpeg', 'gif', 'webp'];
            if (!in_array($ext, $allowed, true)) {
                SessionHelper::flash('error', 'Format logo tidak sah.');
                header('Location: index.php?route=admin/settings');
                exit;
            }

            $filename = 'logo_' . time() . '.' . $ext;
            $target = $uploadDir . '/' . $filename;
            if (!move_uploaded_file($logoFile['tmp_name'], $target)) {
                SessionHelper::flash('error', 'Gagal memindahkan fail logo. Pastikan permission folder betul.');
                header('Location: index.php?route=admin/settings');
                exit;
            }
            if ($logoPath && file_exists($uploadDir . '/' . $logoPath)) {
                @unlink($uploadDir . '/' . $logoPath);
            }
            $logoPath = $filename;
        }

        $settingModel->update([
            'company_name' => $companyName,
            'tagline' => $tagline,
            'email' => $email,
            'phone' => $phone,
            'address' => $address,
            'locations' => $locations,
            'logo_path' => $logoPath,
        ]);

        SettingHelper::refresh();
        SessionHelper::flash('message', 'Maklumat syarikat dikemaskini.');
        header('Location: index.php?route=admin/settings');
    }

    private function uploadErrorMessage(int $code): string
	{
		switch ($code) {
			case UPLOAD_ERR_INI_SIZE:
			case UPLOAD_ERR_FORM_SIZE:
				return 'Fail melebihi saiz maksimum yang dibenarkan (rujuk php.ini).';
			case UPLOAD_ERR_PARTIAL:
				return 'Fail hanya dimuat naik sebahagian.';
			case UPLOAD_ERR_NO_FILE:
				return 'Tiada fail dipilih.';
			case UPLOAD_ERR_NO_TMP_DIR:
				return 'Folder sementara tiada di pelayan.';
			case UPLOAD_ERR_CANT_WRITE:
				return 'Pelayan gagal menulis fail (permission).';
			case UPLOAD_ERR_EXTENSION:
				return 'Muat naik dihalang oleh extension PHP.';
			default:
				return 'Ralat tidak diketahui semasa memuat naik logo.';
		}
	}

    private function payrollSummary(string $status = 'approved', ?int $staffId = null, ?int $month = null, ?int $year = null): array
    {
        $summary = [
            'advance_total' => 0,
            'leave_days' => 0,
            'claim_total' => 0,
        ];

        // Advance Salary total
        $advWhere = ['1=1'];
        $advParams = [];
        if ($status) {
            $advWhere[] = 'status = :adv_status';
            $advParams['adv_status'] = $status;
        }
        if ($staffId) {
            $advWhere[] = 'user_id = :adv_user';
            $advParams['adv_user'] = $staffId;
        }
        $stmt = $this->pdo->prepare(
            'SELECT COALESCE(SUM(jumlah),0) FROM advance_salary WHERE ' . implode(' AND ', $advWhere)
        );
        $stmt->execute($advParams);
        $summary['advance_total'] = (float) $stmt->fetchColumn();

        // Leave days total
        $leaveWhere = ['1=1'];
        $leaveParams = [];
        if ($status) {
            $leaveWhere[] = 'status = :leave_status';
            $leaveParams['leave_status'] = $status;
        }
        if ($staffId) {
            $leaveWhere[] = 'user_id = :leave_user';
            $leaveParams['leave_user'] = $staffId;
        }
        if ($month) {
            $leaveWhere[] = 'MONTH(tarikh_mula) = :month';
            $leaveParams['month'] = $month;
        }
        if ($year) {
            $leaveWhere[] = 'YEAR(tarikh_mula) = :year';
            $leaveParams['year'] = $year;
        }
        $stmt = $this->pdo->prepare(
            'SELECT COALESCE(SUM(jumlah_hari),0) FROM leave_requests WHERE ' . implode(' AND ', $leaveWhere)
        );
        $stmt->execute($leaveParams);
        $summary['leave_days'] = (int) $stmt->fetchColumn();

        // Claims total
        $claimWhere = ['1=1'];
        $claimParams = [];
        if ($status) {
            $claimWhere[] = 'status = :claim_status';
            $claimParams['claim_status'] = $status;
        }
        if ($staffId) {
            $claimWhere[] = 'user_id = :claim_user';
            $claimParams['claim_user'] = $staffId;
        }
        $stmt = $this->pdo->prepare(
            'SELECT COALESCE(SUM(amount),0) FROM claims WHERE ' . implode(' AND ', $claimWhere)
        );
        $stmt->execute($claimParams);
        $summary['claim_total'] = (float) $stmt->fetchColumn();

        return $summary;
    }
}

