<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/**
 * Go-Live Frontend Verification Command
 * Hits critical frontend routes in-process and reports status + response time.
 * Run: php artisan golive:frontend-check
 */
class GoLiveFrontendCheck extends Command
{
    protected $signature = 'golive:frontend-check
                            {--no-auth : Skip auth-required routes}
                            {--threshold=3 : Max seconds per request to pass}';

    protected $description = 'Verify frontend routes respond and meet speed threshold (go-live check)';

    /** @var array<string, string> route name => method */
    protected $publicRoutes = [
        'home' => 'GET',
        'policy.privacy' => 'GET',
        'policy.refund' => 'GET',
        'policy.shipping' => 'GET',
        'policy.cancellation' => 'GET',
        'policy.support' => 'GET',
        'policy.terms' => 'GET',
        'page.about-us' => 'GET',
        'page.contact-us' => 'GET',
        'page.faqs' => 'GET',
        'page.size-care-guide' => 'GET',
        'product.search' => 'GET',
        'cart.index' => 'GET',
        'login' => 'GET',
    ];

    /** Routes that need a slug/param */
    protected $paramRoutes = [
        'collections.show' => ['slug' => 'new-arrivals'],
    ];

    public function handle(): int
    {
        $threshold = (float) $this->option('threshold');
        $skipAuth = $this->option('no-auth');
        $this->info('Go-Live Frontend Check (threshold: ' . $threshold . 's per request)');
        $this->newLine();

        $passed = 0;
        $failed = 0;
        $skipped = 0;
        $results = [];

        foreach ($this->publicRoutes as $name => $method) {
            $result = $this->hitRoute($name, $method, $threshold);
            $results[] = $result;
            if ($result['status'] === 'pass') {
                $passed++;
            } elseif ($result['status'] === 'skip') {
                $skipped++;
            } else {
                $failed++;
            }
        }

        foreach ($this->paramRoutes as $name => $params) {
            $result = $this->hitRoute($name, 'GET', $threshold, $params);
            $results[] = $result;
            if ($result['status'] === 'pass') {
                $passed++;
            } elseif ($result['status'] === 'skip') {
                $skipped++;
            } else {
                $failed++;
            }
        }

        if (!$skipAuth) {
            $authRoutes = [
                'customer.profile' => 'GET',
                'customer.orders.index' => 'GET',
                'checkout.index' => 'GET',
                'wishlist.index' => 'GET',
            ];
            foreach ($authRoutes as $name => $method) {
                $result = $this->hitRoute($name, 'GET', $threshold, [], true);
                $results[] = $result;
                if ($result['status'] === 'pass') {
                    $passed++;
                } elseif ($result['status'] === 'skip') {
                    $skipped++;
                } else {
                    $failed++;
                }
            }
        }

        $this->table(
            ['Route', 'Status', 'HTTP', 'Time (s)', 'Note'],
            array_map(function ($r) {
                return [
                    $r['route'],
                    $r['status'] === 'pass' ? '<info>PASS</info>' : ($r['status'] === 'skip' ? 'SKIP' : '<error>FAIL</error>'),
                    $r['http'] ?? '-',
                    $r['time'] !== null ? number_format($r['time'], 2) : '-',
                    $r['note'] ?? '',
                ];
            }, $results)
        );

        $this->newLine();
        $this->info("Summary: {$passed} passed, {$failed} failed, {$skipped} skipped.");

        if ($failed > 0) {
            $this->error('Some routes failed. Fix before go-live.');
            return self::FAILURE;
        }

        $this->info('All checked routes passed. Frontend route check OK for go-live.');
        return self::SUCCESS;
    }

    private function hitRoute(string $name, string $method, float $threshold, array $params = [], bool $expectRedirect = false): array
    {
        $start = microtime(true);
        $route = Route::getRoutes()->getByName($name);

        if (!$route) {
            return [
                'route' => $name,
                'status' => 'fail',
                'http' => null,
                'time' => null,
                'note' => 'Route not found',
            ];
        }

        try {
            $url = route($name, $params);
            $request = Request::create($url, $method);
            $request->headers->set('Accept', 'text/html');
            $response = app()->handle($request);
            $time = microtime(true) - $start;
            $code = $response->getStatusCode();

            $ok = $code >= 200 && $code < 400;
            if ($expectRedirect && ($code === 302 || $code === 301)) {
                $ok = true;
            }
            $slow = $time > $threshold;

            $status = ($ok && !$slow) ? 'pass' : 'fail';
            $note = '';
            if ($expectRedirect && ($code === 302 || $code === 301)) {
                $note = 'redirect (auth)';
            }
            if ($slow) {
                $note .= ($note ? '; ' : '') . 'slow';
            }
            if (!$ok && $code >= 400) {
                $note .= ($note ? '; ' : '') . "HTTP {$code}";
            }

            return [
                'route' => $name,
                'status' => $status,
                'http' => $code,
                'time' => $time,
                'note' => $note ?: 'OK',
            ];
        } catch (\Throwable $e) {
            $time = microtime(true) - $start;
            return [
                'route' => $name,
                'status' => 'fail',
                'http' => null,
                'time' => $time,
                'note' => $e->getMessage(),
            ];
        }
    }
}
