<?php

namespace Modules\SaasSwitcher\Providers;

use Illuminate\Contracts\Http\Kernel;
use Illuminate\Support\ServiceProvider;
use Modules\SaasSwitcher\Http\Middleware\ResolveProjectConnection;

/**
 * Self-contained wiring for the SaaS switcher. Everything the feature needs is
 * registered here so the module is drop-in portable (copy the folder, enable
 * it, set the PROJ_*_DB env vars):
 *   - one DB connection per project (cloned from the host's `mysql` connection)
 *   - the connection-switch middleware (appended to the `web` group)
 *   - config, views and routes (routes via start.php)
 */
class SaasSwitcherServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->mergeConfigFrom(__DIR__ . '/../Config/config.php', 'saasswitcher');

        // Global helper module_entitled() — loaded here so it is available
        // app-wide WITHOUT editing core app/Http/helpers.php.
        require_once __DIR__ . '/../Support/helpers.php';

        // Per-business module entitlements gate (request-scoped memo).
        $this->app->singleton(\Modules\SaasSwitcher\Support\ModuleEntitlementService::class);

        // entitlements:seed console command.
        if ($this->app->runningInConsole()) {
            $this->commands([\Modules\SaasSwitcher\Console\SeedModuleEntitlements::class]);
        }

        // Register a connection per project by cloning the host's default mysql
        // connection (host/user/pass/charset…) and swapping the database. No
        // edit to config/database.php required.
        $base = config('database.connections.mysql', []);
        foreach (config('saasswitcher.projects', []) as $project) {
            if (empty($project['connection'])) {
                continue;
            }
            config([
                'database.connections.' . $project['connection'] => array_merge($base, [
                    'driver'   => 'mysql',
                    'database' => $project['database'] ?? ($base['database'] ?? null),
                ]),
            ]);
        }

        // (The old EncryptCookies rebind that kept `saas_project` unencrypted for
        // ProjectActivator was removed — module visibility is now DB-driven via
        // module_entitlements, and the active project is read from the session,
        // not a cookie.)
    }

    public function boot(Kernel $kernel): void
    {
        $this->loadViewsFrom(__DIR__ . '/../Resources/views', 'saasswitcher');
        $this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');

        // Route-level alias for the per-business module entitlement guard,
        // e.g. Route::middleware('module:VetClinic'). Backs the DB-driven
        // module visibility that replaces the old saas_project cookie hider.
        $this->app['router']->aliasMiddleware(
            'module',
            \Modules\SaasSwitcher\Http\Middleware\EnsureModuleEntitled::class
        );

        // Run the connection-switch on every web request. It is a no-op until a
        // project user is impersonated, so it never affects normal host usage.
        $kernel->appendMiddlewareToGroup('web', ResolveProjectConnection::class);

        // CRITICAL: it must run AFTER StartSession (needs the session) but BEFORE
        // Authenticate — otherwise auth resolves the user on the host connection
        // instead of the project's. Insert it into the router's middleware
        // priority right after StartSession. (router->middlewarePriority is a
        // public property, so no core file is modified.)
        $router = $this->app['router'];
        $priority = $router->middlewarePriority;
        if (! in_array(ResolveProjectConnection::class, $priority, true)) {
            $idx = array_search(\Illuminate\Session\Middleware\StartSession::class, $priority, true);
            $pos = $idx === false ? 0 : $idx + 1;
            array_splice($priority, $pos, 0, [ResolveProjectConnection::class]);
            $router->middlewarePriority = $priority;
        }
    }
}
