<?php

namespace App\Console\Commands;

use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Throwable;

class SecurityLaunchCheck extends Command
{
    protected $signature = 'raseednow:security-check {--allow-local : Allow local development settings}';

    protected $description = 'Validate launch-critical security settings before production release.';

    public function handle(): int
    {
        $allowLocal = $this->option('allow-local') || app()->environment('local', 'testing');
        $issues = [];

        if (! $allowLocal) {
            $this->productionChecks($issues);
        }

        $this->databaseChecks($issues, $allowLocal);

        if ($issues) {
            foreach ($issues as $issue) {
                $this->error($issue);
            }

            return self::FAILURE;
        }

        $this->info('Security launch checks passed.');

        return self::SUCCESS;
    }

    /**
     * @param  array<int, string>  $issues
     */
    private function productionChecks(array &$issues): void
    {
        if (! app()->environment('production')) {
            $issues[] = 'APP_ENV must be production for launch.';
        }

        if (config('app.debug')) {
            $issues[] = 'APP_DEBUG must be false for launch.';
        }

        if (blank(config('app.key'))) {
            $issues[] = 'APP_KEY must be set.';
        }

        if (! str_starts_with((string) config('app.url'), 'https://')) {
            $issues[] = 'APP_URL must use https://.';
        }

        if (! config('session.encrypt')) {
            $issues[] = 'SESSION_ENCRYPT must be true.';
        }

        if (! config('session.secure')) {
            $issues[] = 'SESSION_SECURE_COOKIE must be true.';
        }

        if (config('session.http_only') !== true) {
            $issues[] = 'SESSION_HTTP_ONLY must be true.';
        }
    }

    /**
     * @param  array<int, string>  $issues
     */
    private function databaseChecks(array &$issues, bool $allowLocal): void
    {
        try {
            DB::connection()->getPdo();
        } catch (Throwable) {
            return;
        }

        if (! $allowLocal && User::whereIn('email', ['admin@raseednow.test', 'player@raseednow.test'])->exists()) {
            $issues[] = 'Seeded local users must not exist in production.';
        }
    }
}
