<?php

declare(strict_types=1);

namespace Builder\Core\Http\Controllers\Settings;

use Builder\Core\Exceptions\UnauthorizedAccessException;
use Builder\Core\Foundation\Registry;
use Builder\Core\Foundation\Settings\SettingsDefinition;
use Builder\Core\Foundation\Settings\SettingsExtension;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

final class ShowSettingsController
{
    public function __construct(private readonly Registry $registry) {}

    public function __invoke(Request $request): Response
    {
        $page = (string) $request->route('page', '');
        $parent = $request->route('parent') !== null ? (string) $request->route('parent') : null;
        $key = $parent !== null ? "{$parent}.{$page}" : $page;
        $definition = $this->registry->resolveSettingsPage($key);

        if ($definition === null) {
            abort(404);
        }

        $this->authorizeAccess($definition->getPage()->getPermission());

        $values = array_merge(
            app($definition->getSettingsClass())->settingsToArray(),
            ...$this->loadExtensionValues($definition),
        );

        return Inertia::render('Settings/Show', [
            'settingsDefinition' => $definition->toArray(),
            'values' => $values,
        ]);
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function loadExtensionValues(SettingsDefinition $definition): array
    {
        return array_map(
            fn (SettingsExtension $ext): array => app($ext::getSettingsClass())->settingsToArray(),
            $definition->getExtensions(),
        );
    }

    private function authorizeAccess(?string $permission): void
    {
        if ($permission === null) {
            return;
        }

        if (! auth()->user()?->can($permission)) {
            throw UnauthorizedAccessException::forPermission($permission);
        }
    }
}
