<?php
class Controller
{
    protected ?Request $requestInstance = null;
    protected ?string $moduleNameCache = null;

    protected function view(string $viewName, array $data = [], string $layout = 'app'): void
    {
        $view = View::getInstance();
        $data['_request'] = $this->request();
        $view->render($viewName, $data, $layout, $this->moduleName());
    }

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

    protected function redirect(string $url, array $flash = []): void
    {
        foreach ($flash as $key => $value) {
            Session::flash($key, $value);
        }
        Response::redirect($url);
    }

    protected function request(): Request
    {
        if ($this->requestInstance === null) {
            $this->requestInstance = new Request();
        }
        return $this->requestInstance;
    }

    public function setRequest(Request $request): void
    {
        $this->requestInstance = $request;
    }

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

    protected function auth(): ?array
    {
        return Auth::user();
    }

    protected function can(string $permission): bool
    {
        return Gate::can($permission);
    }

    protected function abort(int $code, string $message = ''): void
    {
        http_response_code($code);
        $viewFile = ROOT_PATH . '/views/errors/' . $code . '.php';
        if (file_exists($viewFile)) {
            $data = ['message' => $message, 'code' => $code];
            $view = View::getInstance();
            $layout = Auth::check() ? 'app' : 'auth';
            $view->render('errors/' . $code, $data, $layout);
        } else {
            echo "<h1>{$code}</h1><p>{$message}</p>";
        }
        exit;
    }

    protected function flash(string $type, string $message): void
    {
        $existing = Session::getFlash('alerts') ?? [];
        $existing[] = ['type' => $type, 'message' => $message];
        Session::flash('alerts', $existing);
    }

    protected function moduleName(): ?string
    {
        return $this->moduleNameCache;
    }

    public function setModuleName(string $name): void
    {
        $this->moduleNameCache = $name;
    }

    protected function audit(string $action, string $entityType, ?int $entityId, string $description, $oldValues = null, $newValues = null): void
    {
        AuditLog::log($action, $this->moduleName() ?? 'core', $entityType, $entityId, $description, $oldValues, $newValues);
    }
}