<?php
namespace App\Core;

/** Kendali akses berbasis peran (RBAC) + pembatasan cakupan data. */
class Acl
{
    private static ?array $perms = null;

    /** Daftar izin pengguna aktif dalam bentuk "modul.aksi". */
    public static function permissions(): array
    {
        if (self::$perms !== null) return self::$perms;
        self::$perms = [];
        if (!Auth::check()) return self::$perms;
        $u = Auth::user();
        if (!$u) return self::$perms;

        $rows = Database::i()->all(
            'SELECT DISTINCT p.module, p.action
               FROM permissions p
               JOIN role_permissions rp ON rp.permission_id = p.id
              WHERE rp.role_id = :r
                 OR rp.role_id IN (SELECT role_id FROM user_roles WHERE user_id = :u)',
            ['r' => (int)$u['role_id'], 'u' => (int)$u['id']]
        );
        foreach ($rows as $r) self::$perms[$r['module'] . '.' . $r['action']] = true;
        return self::$perms;
    }

    public static function can(string $module, string $action = 'view'): bool
    {
        if (!Auth::check()) return false;
        if (Auth::isSuper()) return true;
        return isset(self::permissions()[$module . '.' . $action]);
    }

    public static function canAny(array $pairs): bool
    {
        foreach ($pairs as $p) {
            [$m, $a] = array_pad(explode('.', $p, 2), 2, 'view');
            if (self::can($m, $a)) return true;
        }
        return false;
    }

    /** Menghentikan permintaan bila tidak berizin. */
    public static function require(string $module, string $action = 'view'): void
    {
        if (!self::can($module, $action)) {
            Logger::warning('Akses ditolak: ' . Auth::name() . " -> {$module}.{$action}");
            Response::abort(403, 'Anda tidak memiliki hak akses untuk ' . self::actionLabel($action) . ' pada modul ' . $module . '.');
        }
    }

    public static function actionLabel(string $a): string
    {
        return [
            'view' => 'melihat', 'create' => 'menambah', 'edit' => 'mengubah', 'delete' => 'menghapus',
            'approve' => 'menyetujui', 'import' => 'mengimpor', 'export' => 'mengekspor', 'print' => 'mencetak',
        ][$a] ?? $a;
    }

    /** Cakupan data pengguna: 'all' | 'own_collection' | 'own_sales' | 'own_area'. */
    public static function scope(): string
    {
        $u = Auth::user();
        if (!$u) return 'none';
        if (Auth::isSuper()) return 'all';
        return $u['data_scope'] ?? 'all';
    }

    /**
     * Menghasilkan potongan SQL pembatas data untuk tabel invoice.
     * @param string $alias alias tabel invoices dalam query
     * @return array{0:string,1:array} [klausa SQL, parameter]
     */
    public static function invoiceScopeSql(string $alias = 'i'): array
    {
        $u = Auth::user();
        $scope = self::scope();
        if ($scope === 'all' || !$u) return ['1=1', []];

        // Perilaku bila akun belum ditautkan ke master sales / petugas penagihan / area.
        // Mode ketat (default) menutup akses — lebih aman untuk data keuangan —
        // dan sistem menampilkan peringatan agar administrator segera menautkannya.
        $ketat = \App\Core\Settings::bool('keamanan.cakupan_data_ketat', true);
        $belumDipetakan = $ketat ? ['1=0', []] : ['1=1', []];

        if ($scope === 'own_collection') {
            $coId = (int)($u['collection_officer_id'] ?? 0);
            if ($coId <= 0) return $belumDipetakan;
            return ["{$alias}.collection_officer_id = :scope_co", ['scope_co' => $coId]];
        }
        if ($scope === 'own_sales') {
            $spId = (int)($u['salesperson_id'] ?? 0);
            if ($spId <= 0) return $belumDipetakan;
            return ["{$alias}.salesperson_id = :scope_sp", ['scope_sp' => $spId]];
        }
        if ($scope === 'own_area') {
            $aId = (int)($u['area_id'] ?? 0);
            if ($aId <= 0) return $belumDipetakan;
            return ["{$alias}.area_id = :scope_area", ['scope_area' => $aId]];
        }
        return ['1=1', []];
    }

    /**
     * Peringatan bila akun memiliki cakupan data terbatas tetapi belum ditautkan
     * ke data master, sehingga tidak ada data yang dapat ditampilkan.
     * @return string|null pesan peringatan berbahasa Indonesia, atau null bila aman
     */
    public static function scopeWarning(): ?string
    {
        $u = Auth::user();
        if (!$u) return null;
        $scope = self::scope();
        [$field, $master] = match ($scope) {
            'own_collection' => ['collection_officer_id', 'petugas penagihan'],
            'own_sales'      => ['salesperson_id', 'sales'],
            'own_area'       => ['area_id', 'area'],
            default          => [null, null],
        };
        if ($field === null || (int)($u[$field] ?? 0) > 0) return null;

        return \App\Core\Settings::bool('keamanan.cakupan_data_ketat', true)
            ? 'Akun Anda dibatasi pada data ' . $master . ' tertentu, tetapi belum ditautkan ke data master '
              . $master . '. Karena itu belum ada data yang dapat ditampilkan. '
              . 'Hubungi administrator untuk menautkan akun Anda melalui menu Pengguna.'
            : 'Akun Anda belum ditautkan ke data master ' . $master
              . ', sehingga untuk sementara seluruh data ditampilkan. Hubungi administrator untuk menautkan akun Anda.';
    }

    public static function reset(): void { self::$perms = null; }

    /** Daftar menu utama beserta izin minimal yang dibutuhkan. */
    public static function menu(): array
    {
        return [
            ['label' => 'Dashboard',        'icon' => 'speedometer2',       'url' => '/',                  'perm' => 'dashboard.view'],
            ['label' => 'Piutang',          'icon' => 'cash-stack',         'url' => '/piutang',           'perm' => 'piutang.view',
             'children' => [
                ['label' => 'Daftar Piutang',      'url' => '/piutang',                'perm' => 'piutang.view'],
                ['label' => 'Aging Piutang',       'url' => '/aging',                  'perm' => 'aging.view'],
                ['label' => 'Kartu Piutang',       'url' => '/kartu-piutang',          'perm' => 'kartu_piutang.view'],
                ['label' => 'ACP / Kinerja',       'url' => '/acp',                    'perm' => 'acp.view'],
                ['label' => 'Perkiraan Kas',       'url' => '/forecast',               'perm' => 'forecast.view'],
                ['label' => 'Kualitas Data',       'url' => '/kualitas-data',          'perm' => 'kualitas_data.view'],
             ]],
            ['label' => 'Invoice',          'icon' => 'receipt',            'url' => '/invoice',           'perm' => 'invoice.view'],
            ['label' => 'Pembayaran',       'icon' => 'wallet2',            'url' => '/pembayaran',        'perm' => 'pembayaran.view'],
            ['label' => 'Penagihan',        'icon' => 'telephone-outbound', 'url' => '/penagihan',         'perm' => 'penagihan.view',
             'children' => [
                ['label' => 'Worklist Penagihan',  'url' => '/penagihan',              'perm' => 'penagihan.view'],
                ['label' => 'Riwayat Follow-up',   'url' => '/penagihan/riwayat',      'perm' => 'penagihan.view'],
                ['label' => 'Janji Bayar',         'url' => '/penagihan/janji-bayar',  'perm' => 'penagihan.view'],
             ]],
            ['label' => 'Revisi Invoice',   'icon' => 'arrow-repeat',       'url' => '/revisi',            'perm' => 'revisi.view'],
            ['label' => 'Nota Kredit',      'icon' => 'file-earmark-minus', 'url' => '/nota-kredit',       'perm' => 'nota_kredit.view'],
            ['label' => 'Import Data',      'icon' => 'file-earmark-excel', 'url' => '/import',            'perm' => 'import.view'],
            ['label' => 'Laporan',          'icon' => 'file-earmark-bar-graph', 'url' => '/laporan',       'perm' => 'laporan.view'],
            ['label' => 'Pembuat Laporan',  'icon' => 'sliders',            'url' => '/pembuat-laporan',   'perm' => 'report_builder.view'],
            ['label' => 'Data Master',      'icon' => 'database',           'url' => '/master',            'perm' => 'master.view'],
            ['label' => 'Persetujuan',      'icon' => 'check2-square',      'url' => '/persetujuan',       'perm' => 'persetujuan.view'],
            ['label' => 'Pengguna',         'icon' => 'people',             'url' => '/pengguna',          'perm' => 'pengguna.view'],
            ['label' => 'Log Aktivitas',    'icon' => 'clock-history',      'url' => '/log-aktivitas',     'perm' => 'audit.view'],
            ['label' => 'Pengaturan',       'icon' => 'gear',               'url' => '/pengaturan',        'perm' => 'pengaturan.view'],
            ['label' => 'Pencadangan Data', 'icon' => 'hdd',                'url' => '/pencadangan',       'perm' => 'backup.view'],
        ];
    }
}
