<?php

declare(strict_types=1);

namespace App\Core;

/**
 * BaseController
 *
 * Every future controller (LeadController, CustomerController, ...)
 * extends this. It provides the small set of things nearly every
 * action needs — rendering a view inside the shared layout, returning
 * JSON, grabbing the authenticated user, redirecting with flashed
 * input/errors — without forcing a particular way of organizing the
 * business logic itself (that's what app/services is for).
 */
abstract class BaseController
{
    /**
     * Renders app/views/{$view}.php inside the shared layout at
     * app/views/layouts/app.php. Pass $useLayout = false for partials
     * or standalone pages (e.g. the login screen, which has its own
     * full-page markup already in the frontend templates).
     */
    protected function view(string $view, array $data = [], bool $useLayout = true): Response
    {
        $viewPath = dirname(__DIR__) . "/views/{$view}.php";

        if (!is_file($viewPath)) {
            throw new \RuntimeException("View not found: {$view}");
        }

        $render = function () use ($viewPath, $data): string {
            extract($data, EXTR_SKIP);
            ob_start();
            require $viewPath;

            return (string) ob_get_clean();
        };

        if (!$useLayout) {
            return Response::html($render());
        }

        $layoutPath = dirname(__DIR__) . '/views/layouts/app.php';
        $content = $render();

        ob_start();
        extract($data, EXTR_SKIP);
        require $layoutPath;
        $html = (string) ob_get_clean();

        return Response::html($html);
    }

    protected function json(mixed $data, int $status = 200): Response
    {
        return Response::json($data, $status);
    }

    protected function redirect(string $path): Response
    {
        return Response::redirect(str_starts_with($path, 'http') ? $path : base_url($path));
    }

    protected function redirectBack(Request $request): Response
    {
        $referer = $request->header('Referer') ?? base_url();

        return Response::redirect($referer);
    }

    /** Flash validation errors + submitted input, then redirect back — the classic "server-rendered form" failure path. */
    protected function withErrors(Request $request, array $errors, string $backTo): Response
    {
        Session::flash('_errors', $errors);
        Session::flash('_old_input', $request->all());

        return $this->redirect($backTo);
    }

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

    protected function currentUserId(): ?int
    {
        $user = Auth::user();

        return $user ? (int) $user['id'] : null;
    }

    /** Validate and short-circuit with a 422 JSON response on failure — the common case for AJAX-driven forms. */
    protected function validateOrFail(Request $request, array $rules, array $messages = []): array
    {
        $validator = Validator::make($request->all(), $rules, $messages);

        if ($validator->fails()) {
            throw new ValidationException($validator->errors());
        }

        return $validator->validated();
    }
}
