<?php
declare(strict_types=1);

namespace App\Core;

abstract class Controller
{
    protected Request $request;

    public function __construct()
    {
    }

    protected function view(string $viewPath, array $data = []): Response
    {
        $template = new Template();
        $html = $template->render($viewPath, $data);

        $response = new Response();
        return $response->html($html);
    }

    protected function json($data, int $status = 200): Response
    {
        $response = new Response();
        return $response->json($data, $status);
    }

    protected function redirect(string $url): Response
    {
        return new Response($url);
    }

    protected function back(): Response
    {
        $referer = $_SERVER['HTTP_REFERER'] ?? '/';
        return new Response($referer);
    }

    protected function validate(array $data, array $rules): array
    {
        $validator = new Validator();
        $result = $validator->validate($data, $rules);

        if ($result->fails()) {
            $session = App::getInstance()->session();
            $session->flash('_old_input', $data);
            $errors = $result->errors();
            $alerts = [];
            foreach ($errors as $field => $fieldErrors) {
                foreach ($fieldErrors as $error) {
                    $alerts[] = ['type' => 'error', 'message' => $error];
                }
            }
            $session->flash('_alerts', $alerts);
        }

        return $data;
    }

    protected function validated(array $data, array $rules): array
    {
        $validator = new Validator();
        $result = $validator->validate($data, $rules);
        if ($result->fails()) {
            $session = App::getInstance()->session();
            $session->flash('_old_input', $data);
            $alerts = [];
            foreach ($result->errors() as $field => $fieldErrors) {
                foreach ($fieldErrors as $error) {
                    $alerts[] = ['type' => 'error', 'message' => $error];
                }
            }
            $session->flash('_alerts', $alerts);
            throw new Exceptions\ValidationException($result->errors());
        }
        return $result->validated();
    }

    protected function authorize(string $permission): void
    {
        $employee = App::getInstance()->currentEmployee();
        if (!$employee) {
            throw new \RuntimeException('Unauthorized', 401);
        }
        if (method_exists($employee, 'hasPermission') && !$employee->hasPermission($permission)) {
            throw new \RuntimeException('Forbidden', 403);
        }
    }

    protected function currentEmployee(): ?object
    {
        return App::getInstance()->currentEmployee();
    }
}