<?php
namespace App\Core;

/** Controller dasar. */
abstract class Controller
{
    /** Modul untuk pemeriksaan izin default. */
    protected string $module = '';

    protected function db(): Database { return Database::i(); }

    protected function view(string $view, array $data = [], ?string $layout = null): void
    {
        $data['modul_aktif'] = $data['modul_aktif'] ?? $this->module;
        View::render($view, $data, $layout);
    }

    protected function json($data, int $code = 200): void { Response::json($data, $code); }

    protected function redirect(string $url, int $code = 302): void { Response::redirect($url, $code); }

    protected function back(string $fallback = '/'): void { Response::back($fallback); }

    protected function can(string $action = 'view', ?string $module = null): bool
    {
        return Acl::can($module ?? $this->module, $action);
    }

    protected function requirePerm(string $action = 'view', ?string $module = null): void
    {
        Acl::require($module ?? $this->module, $action);
    }

    protected function requirePost(): void
    {
        if (!Request::isPost() && !in_array(Request::method(), ['PUT', 'PATCH', 'DELETE'], true)) {
            Response::abort(405, 'Metode permintaan tidak diizinkan.');
        }
        Csrf::verifyOrFail();
    }

    /** Validasi; bila gagal kembali ke halaman sebelumnya dengan pesan. */
    protected function validate(array $rules, array $labels = [], ?string $backTo = null): array
    {
        $data = Request::all();
        $v = Validator::make($data, $rules, $labels);
        if ($v->fails()) {
            Flash::keepInput($data);
            Flash::keepErrors($v->errors());
            foreach ($v->allMessages() as $m) Flash::error($m);
            if (Request::isAjax()) $this->json(['sukses' => false, 'pesan' => $v->firstError(), 'errors' => $v->errors()], 422);
            $backTo ? $this->redirect($backTo) : $this->back();
        }
        Flash::clearOld();
        return $data;
    }

    protected function user(): ?array { return Auth::user(); }
    protected function userId(): int  { return Auth::id(); }

    /** Nilai halaman & jumlah baris per halaman dari query string. */
    protected function pageParams(int $defaultPerPage = 0): array
    {
        $per = $defaultPerPage ?: Settings::int('laporan.baris_per_halaman', 50);
        return [
            max(1, Request::int('hal', 1)),
            max(10, min(1000, Request::int('per', $per))),
        ];
    }
}
