<?php

declare(strict_types=1);

namespace Builder\Seo;

use Builder\Core\Foundation\Definition\Field;
use Builder\Core\Foundation\Definition\JsModule;
use Builder\Core\Foundation\Definition\MenuItem;
use Builder\Core\Foundation\Registry;
use Builder\Core\Http\Controllers\Settings\ShowSettingsController;
use Builder\Seo\Http\Middleware\HandleRedirects;
use Builder\Seo\Resources\RedirectResource;
use Builder\Seo\Settings\SeoSettings;
use Builder\Seo\Support\SeoField;
use Composer\InstalledVersions;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;

final class SeoServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind('builder.seo', fn (): bool => true);

        $this->mergeConfigFrom(__DIR__.'/../config/seo.php', 'seo');
    }

    public function boot(Registry $registry): void
    {
        $this->loadTranslationsFrom(__DIR__.'/../lang', 'seo');
        $this->loadMigrationsFrom(__DIR__.'/../database/migrations');

        $registry->translationNamespace('seo', 'seo::seo');

        $registry->register(
            JsModule::make()
                ->setKey('seo')
                ->setLabel('SEO')
                ->setEntry('resources/js/index.ts')
                ->setPublicPath(__DIR__.'/../public')
                ->setVersion(rescue(fn () => InstalledVersions::getPrettyVersion('builder/seo')))
                ->setAuthor('Every Day')
                ->setAuthorUrl('https://every-day.nl'),
        );

        if ((bool) config('seo.settings_page', true)) {
            $registry->settingsPage(SeoSettings::class);
        }

        $registry->resource(RedirectResource::class);

        $registry->permissions('manage:seo', 'read:redirects', 'create:redirects', 'update:redirects', 'delete:redirects');

        $registry->menuItem(
            MenuItem::make('seo')
                ->label(fn (): string => (string) __('seo::seo.nav.label'))
                ->icon('Search')
                ->priority(85)
                ->permission('manage:seo')
                ->children([
                    MenuItem::make('seo.redirects')
                        ->label(fn (): string => (string) __('seo::seo.nav.redirects'))
                        ->namedRoute('builder.resource.index', ['resource' => 'redirects'])
                        ->permission('read:redirects'),
                    MenuItem::make('seo.settings')
                        ->label(fn (): string => (string) __('seo::seo.nav.settings'))
                        ->namedRoute('builder.seo.settings.show')
                        ->permission('manage:seo'),
                ]),
        );

        $this->registerSeoSettingsRoute();

        Blueprint::macro('seoColumns', function (): void {
            /** @var Blueprint $this */
            $this->string('seo_title', 70)->nullable();
            $this->text('seo_description')->nullable();
            $this->string('seo_robots', 50)->nullable()->default('index');
        });

        Field::macro('seo', fn (string $name = 'seo'): Field => Field::make($name)
            ->component('FieldSeoInput')
            ->meta('fields', SeoField::getFields())
            ->meta('no_index_select', true));

        if ((bool) config('seo.handle_redirects', true)) {
            $this->app->make(Kernel::class)->pushMiddleware(HandleRedirects::class);
        }
    }

    private function registerSeoSettingsRoute(): void
    {
        Route::middleware([
            ...config('builder.middleware', ['web']),
            'builder.locale',
            'builder.inertia',
            'builder.auth',
            'builder.mfa',
        ])
            ->prefix(config('builder.prefix', 'admin'))
            ->name('builder.')
            ->group(function (): void {
                Route::get('/seo/settings', ShowSettingsController::class)
                    ->defaults('page', 'seo')
                    ->name('seo.settings.show');
            });
    }
}
