<?php

declare(strict_types=1);

namespace App\Providers;

use App\Filament\Schemas\VianaResourceFormSchemaClassGenerator;
use App\Filament\Schemas\VianaResourceTableClassGenerator;
use Dedoc\Scramble\Scramble;
use Dedoc\Scramble\Support\Generator\OpenApi;
use Dedoc\Scramble\Support\Generator\Operation;
use Dedoc\Scramble\Support\Generator\SecurityScheme;
use Dedoc\Scramble\Support\RouteInfo;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Actions\DeleteAction;
use Filament\Actions\EditAction;
use Filament\Actions\ViewAction;
use Filament\Commands\FileGenerators\Resources\Schemas\ResourceFormSchemaClassGenerator;
use Filament\Commands\FileGenerators\Resources\Schemas\ResourceTableClassGenerator;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Support\Enums\Size;
use Filament\Support\Facades\FilamentView;
use Filament\Tables\Enums\FiltersLayout;
use Filament\Tables\Table;
use Filament\Tables\View\TablesRenderHook;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
use Laravel\Sanctum\PersonalAccessToken;
use Laravel\Sanctum\Sanctum;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        // if ($this->app->environment('local') && class_exists(\Laravel\Telescope\TelescopeServiceProvider::class)) {
        //     $this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class);
        //     $this->app->register(TelescopeServiceProvider::class);
        // }
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        config(['app.url' => rtrim((string) config('app.url'), '/')]);

        URL::forceScheme('https');
        request()->server->set('HTTPS', request()->header('X-Forwarded-Proto', 'https') == 'https' ? 'on' : 'off');
        JsonResource::withoutWrapping();
        Collection::macro('paginate', function ($perPage = 15, $total = null, $page = null, $pageName = 'page'): LengthAwarePaginator {
            $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);

            return new LengthAwarePaginator(
                $this->forPage($page, $perPage)->values(),
                $total ?: $this->count(),
                $perPage,
                $page,
                [
                    'path' => LengthAwarePaginator::resolveCurrentPath(),
                    'pageName' => $pageName,
                ]
            );
        });
        // Optional: Set token expiration times
        // Passport::tokensExpireIn(now()->addDays(15));
        // Passport::refreshTokensExpireIn(now()->addDays(30));
        // Passport::enablePasswordGrant();
        Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
        app()->bind(ResourceTableClassGenerator::class, VianaResourceTableClassGenerator::class);
        app()->bind(ResourceFormSchemaClassGenerator::class, VianaResourceFormSchemaClassGenerator::class);
        Model::preventLazyLoading(! app()->isProduction());

        TextInput::configureUsing(function (TextInput $textInput): void {
            $textInput->translateLabel();
        });
        Select::configureUsing(function (Select $select): void {
            $select->translateLabel();
        });
        Table::configureUsing(function (Table $table): void {
            $table
                ->paginated(true)
                ->paginationPageOptions([10, 25, 50, 100, 'all'])
                ->defaultPaginationPageOption(25)
                ->extremePaginationLinks()
                ->scrollToTopOnPageChange()
                ->deferLoading()
                ->striped()
                ->modifyUngroupedRecordActionsUsing(fn (Action $action) => $action->button()->size(Size::ExtraSmall))
                ->filtersLayout(FiltersLayout::Modal);
        });

        FilamentView::registerRenderHook(
            TablesRenderHook::TOOLBAR_AFTER,
            fn (): \Illuminate\Contracts\View\View => view('filament.components.table-loading-overlay')
        );

        Scramble::configure()
            ->withDocumentTransformers(function (OpenApi $openApi) {
                $openApi->secure(SecurityScheme::http('bearer', 'token'));
            })
            ->withOperationTransformers(function (Operation $operation, RouteInfo $routeInfo) {
                $routeMiddleware = $routeInfo->route->gatherMiddleware();

                $hasAuthMiddleware = false;
                foreach ($routeMiddleware as $middleware) {
                    if (Str::startsWith($middleware, 'auth:')) {
                        $hasAuthMiddleware = true;
                        break;
                    }
                }

                if (! $hasAuthMiddleware) {
                    $operation->security = [];
                }
            });
    }
}
