<?php

namespace App\Providers;

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
use Nwidart\Modules\Facades\Module;

class RouteServiceProvider extends ServiceProvider
{
    /**
     * The path to the "home" route for your application.
     *
     * This is used by Laravel authentication to redirect users after login.
     *
     * @var string
     */
    public const HOME = '/home';

    /**
     * The controller namespace for the application.
     *
     * When present, controller route declarations will automatically be prefixed with this namespace.
     *
     * @var string|null
     */
    protected $namespace = 'App\\Http\\Controllers';

    protected $superAdminNamespace = 'App\\SuperAdmin\\Http\\Controllers';


    /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @return void
     */
    public function boot()
    {
        $this->configureRateLimiting();

        // Register custom route macro for dynamic Livewire components
        $this->registerDynamicLivewireRoute();

        $this->routes(function () {
            // Running Migration
            if (file_exists(public_path() . '/migrate')) {
                Route::middleware('web')
                    ->namespace($this->namespace)
                    ->group(base_path('routes/migrate.php'));
            }

            if (app_type() == 'saas' && file_exists(storage_path('installed'))) {
                Route::middleware('web')
                    ->namespace($this->superAdminNamespace)
                    ->group(base_path('app/SuperAdmin/routes/front.php'));
            }

            if (file_exists(storage_path('installed'))) {
                Route::middleware('web')
                    ->namespace($this->namespace)
                    ->group(base_path('routes/front.php'));
            }

            if (app_type() == 'non-saas') {
                Route::middleware('web')
                    ->namespace($this->namespace)
                    ->group(base_path('routes/app.php'));
            } else {
                Route::middleware('web')
                    ->namespace($this->superAdminNamespace)
                    ->group(base_path('app/SuperAdmin/routes/app.php'));
            }

            Route::middleware('web')
                ->namespace($this->namespace)
                ->group(base_path('routes/web.php'));

            if (app_type() == 'saas') {
                Route::middleware('web')
                    ->namespace($this->superAdminNamespace)
                    ->group(base_path('app/SuperAdmin/routes/superadmin.php'));
            }

            Route::middleware('web')
                ->namespace($this->namespace)
                ->group(base_path('routes/common.php'));

            // Register front.web routes for all enabled modules
            $this->registerModuleFrontRoutes();

            if (app_type() == 'non-saas') {
                Route::middleware('web')
                    ->namespace($this->namespace)
                    ->group(base_path('routes/main.php'));
            } else {
                Route::middleware('web')
                    ->namespace($this->superAdminNamespace)
                    ->group(base_path('app/SuperAdmin/routes/main.php'));
            }
        });
    }

    /**
     * Configure the rate limiters for the application.
     *
     * @return void
     */
    protected function configureRateLimiting()
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
        });
    }

    /**
     * Register front.web routes for all enabled modules.
     *
     * This function parses all enabled modules and registers the front.web.php
     * route file if it exists in the module's routes directory.
     *
     * Note: No namespace is applied to allow Livewire full-page components.
     * Controllers should use fully qualified class names or `use` statements.
     *
     * @return void
     */
    protected function registerModuleFrontRoutes()
    {
        $modules = Module::allEnabled();

        foreach ($modules as $module) {
            $moduleName = $module->getName();
            $frontRoutePath = base_path("Modules/{$moduleName}/routes/front.php");

            if (file_exists($frontRoutePath)) {
                Route::middleware('web')
                    ->group($frontRoutePath);
            }
        }
    }

    /**
     * Register a custom route macro for dynamic Livewire component loading.
     *
     * This allows routes to dynamically determine which Livewire component to load
     * based on runtime logic (e.g., database settings from website table).
     *
     * Usage:
     * Route::dynamicLivewire('/w/{slug}', function($slug) {
     *     $website = Website::where('slug', $slug)->first();
     *     $themeName = $website->theme_name ?? 'tailwind_theme';
     *     return $themeName . '::pages.homepage';
     * });
     *
     * @return void
     */
    protected function registerDynamicLivewireRoute(): void
    {
        Route::macro('dynamicLivewire', function (string $uri, callable $componentResolver) {
            return Route::get($uri, function () use ($componentResolver) {
                // Get route parameters from the current route
                $routeParams = request()->route()->parameters();

                // Set URL defaults so route() helper works without passing parameters
                // This allows route('landing.home') to work without explicitly passing slug
                \Illuminate\Support\Facades\URL::defaults($routeParams);

                // Call the resolver with route parameters to get the component name
                $componentName = $componentResolver(...array_values($routeParams));

                // Create the component with route parameters passed to mount()
                // Livewire 4 uses app('livewire')->new() and then __invoke
                $component = app('livewire')->new($componentName, $routeParams);

                return app()->call([$component, '__invoke']);
            });
        });
    }
}
