<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

/**
 * On a fresh install (release ZIP unzipped, .env created from .env.example),
 * APP_KEY is empty and Laravel's cookie middleware 500s on every request
 * with `MissingAppKeyException` — before the install wizard can route.
 *
 * Buyers without SSH access can't run `php artisan key:generate` to fix it,
 * so this provider runs ahead of the encrypter and auto-generates a key on
 * the first HTTP request when one is missing. Writes it back to .env so
 * subsequent requests use the same key (otherwise sessions / encrypted
 * cookies would invalidate per-request).
 *
 * Skipped in console context — CLI users can still run `php artisan
 * key:generate` if they prefer the explicit path.
 *
 * Registered ahead of AppServiceProvider in bootstrap/providers.php so the
 * key is in place before any other provider needs the encrypter.
 */
class EnsureAppKeyServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        if ($this->app->runningInConsole()) {
            return;
        }

        // Step 1: ensure .env exists. Release ZIP ships .env.example only
        // (no .env — buyers shouldn't see "default credentials" sitting in
        // their docroot). Bootstrap a fresh .env from the template on
        // first hit so the rest of this provider has a file to write to.
        $envPath = $this->app->environmentFilePath();
        if (! file_exists($envPath)) {
            $examplePath = $this->app->basePath('.env.example');
            if (file_exists($examplePath) && is_writable(dirname($envPath))) {
                @copy($examplePath, $envPath);
            }
        }

        $current = config('app.key') ?? env('APP_KEY');
        if (! empty($current)) {
            return;
        }

        $key = 'base64:'.base64_encode(random_bytes(32));

        // Step 2: persist the key to .env so it survives across requests.
        // Without this, every request would generate a new key and
        // invalidate any existing session / encrypted cookie.
        if (is_writable($envPath)) {
            $contents = (string) @file_get_contents($envPath);
            if (preg_match('/^APP_KEY=.*$/m', $contents) === 1) {
                $contents = preg_replace('/^APP_KEY=.*$/m', "APP_KEY={$key}", $contents);
            } else {
                $contents = rtrim($contents)."\nAPP_KEY={$key}\n";
            }
            @file_put_contents($envPath, $contents);
        }

        // Step 3: update runtime config + env vars so this request can
        // proceed even if the .env write failed (e.g. wrong permissions).
        // The encrypter reads config('app.key') lazily, so as long as we
        // set it here it'll be present when middleware first needs it.
        config(['app.key' => $key]);
        putenv("APP_KEY={$key}");
        $_ENV['APP_KEY'] = $key;
        $_SERVER['APP_KEY'] = $key;
    }
}
