<?php
namespace App\Controllers;

use App\Core\Audit;
use App\Core\Controller;
use App\Core\Database;
use App\Core\Dates;
use App\Core\Request;
use App\Core\Response;
use App\Core\Settings;
use App\Services\ExportService;

/** Log aktivitas (audit trail). */
class AuditController extends Controller
{
    protected string $module = 'audit';

    private function filters(): array
    {
        $f = [];
        foreach (['cari', 'module', 'action', 'entity_type'] as $k) {
            $v = trim((string)Request::get($k, ''));
            if ($v !== '') $f[$k] = $v;
        }
        $u = Request::int('user_id'); if ($u > 0) $f['user_id'] = $u;
        foreach (['dari', 'sampai'] as $k) { $d = Request::date($k); if ($d) $f[$k] = $d; }
        return $f;
    }

    /** @return array{0:string,1:array} */
    private function where(array $f): array
    {
        $w = ['1=1'];
        $p = [];
        if (!empty($f['cari'])) {
            $w[] = '(a.description LIKE :q OR a.user_name LIKE :q OR a.entity_type LIKE :q OR a.ip_address LIKE :q)';
            $p['q'] = '%' . $f['cari'] . '%';
        }
        if (!empty($f['module']))      { $w[] = 'a.module = :m';      $p['m'] = $f['module']; }
        if (!empty($f['action']))      { $w[] = 'a.action = :ac';     $p['ac'] = $f['action']; }
        if (!empty($f['entity_type'])) { $w[] = 'a.entity_type = :et';$p['et'] = $f['entity_type']; }
        if (!empty($f['user_id']))     { $w[] = 'a.user_id = :u';     $p['u'] = (int)$f['user_id']; }
        if (!empty($f['dari']))        { $w[] = 'DATE(a.created_at) >= :d1'; $p['d1'] = $f['dari']; }
        if (!empty($f['sampai']))      { $w[] = 'DATE(a.created_at) <= :d2'; $p['d2'] = $f['sampai']; }
        return [implode(' AND ', $w), $p];
    }

    public function index(): void
    {
        $f = $this->filters();
        [$where, $p] = $this->where($f);
        [$page, $per] = $this->pageParams();
        $db = Database::i();
        $m = new \App\Models\AuditLog();
        $res = $m->paginate(
            "SELECT a.* FROM audit_logs a WHERE $where ORDER BY a.created_at DESC, a.id DESC",
            $p, $page, $per, "SELECT COUNT(*) FROM audit_logs a WHERE $where"
        );
        $this->view('audit/index', [
            'judul' => 'Log Aktivitas',
            'subjudul' => 'Jejak audit seluruh aksi penting di dalam sistem',
            'p' => $res, 'filters' => $f,
            'modules' => $db->column('SELECT DISTINCT module FROM audit_logs ORDER BY module'),
            'actions' => $db->column('SELECT DISTINCT action FROM audit_logs ORDER BY action'),
            'entities' => $db->column('SELECT DISTINCT entity_type FROM audit_logs WHERE entity_type IS NOT NULL ORDER BY entity_type'),
            'users' => $db->all('SELECT id, name FROM users WHERE deleted_at IS NULL ORDER BY name'),
            'stat' => $db->one("SELECT COUNT(*) total,
                    SUM(DATE(created_at) = CURDATE()) hari_ini,
                    COUNT(DISTINCT user_id) pengguna FROM audit_logs"),
        ]);
    }

    public function show(array $params): void
    {
        $id = (int)($params['id'] ?? 0);
        $row = Database::i()->one('SELECT * FROM audit_logs WHERE id = :id', ['id' => $id]);
        if (!$row) Response::abort(404, 'Log aktivitas tidak ditemukan.');
        $this->view('audit/detail', [
            'judul' => 'Log Aktivitas #' . $id,
            'subjudul' => Audit::actionLabel($row['action']) . ' pada modul ' . $row['module'],
            'row' => $row, 'old' => arr($row['old_values']), 'new' => arr($row['new_values']),
        ]);
    }

    public function export(): void
    {
        $f = $this->filters();
        [$where, $p] = $this->where($f);
        $rows = Database::i()->all(
            "SELECT a.* FROM audit_logs a WHERE $where ORDER BY a.created_at DESC LIMIT "
            . Settings::int('laporan.maks_baris_export', 50000), $p
        );
        foreach ($rows as &$r) $r['action_label'] = Audit::actionLabel($r['action']);
        unset($r);
        ExportService::send((string)Request::get('format', 'xlsx'), [
            'judul' => 'LOG AKTIVITAS SISTEM',
            'periode' => (!empty($f['dari']) || !empty($f['sampai']))
                ? Dates::fmt($f['dari'] ?? null) . ' s/d ' . Dates::fmt($f['sampai'] ?? null) : 'Seluruh periode',
            'nama_berkas' => 'log_aktivitas', 'sheet' => 'Log Aktivitas', 'orientasi' => 'landscape',
        ], [
            ['label' => 'Waktu',       'key' => 'created_at',   'type' => 'text'],
            ['label' => 'Pengguna',    'key' => 'user_name',    'type' => 'text'],
            ['label' => 'Modul',       'key' => 'module',       'type' => 'text'],
            ['label' => 'Aksi',        'key' => 'action_label', 'type' => 'text'],
            ['label' => 'Entitas',     'key' => 'entity_type',  'type' => 'text'],
            ['label' => 'ID Entitas',  'key' => 'entity_id',    'type' => 'int'],
            ['label' => 'Keterangan',  'key' => 'description',  'type' => 'text', 'width' => 60, 'pdf_width' => 3],
            ['label' => 'Alamat IP',   'key' => 'ip_address',   'type' => 'text'],
        ], $rows);
    }
}
