<?php

namespace App\Services\Installer;

/**
 * Pure read-only environment probe for the install wizard's first step.
 * Each check returns a tuple {label, ok, hint} so the Blade view can
 * render a checklist and the buyer knows what to fix without having to
 * read the PHP error log.
 */
class RequirementsChecker
{
    /**
     * @return array<int, array{label: string, ok: bool, hint: string|null}>
     */
    public function checks(): array
    {
        return [
            $this->phpVersion(),
            $this->extension('pdo_mysql', 'Required to talk to MySQL.'),
            $this->extension('mbstring', 'Required by Laravel core.'),
            $this->extension('openssl', 'Required by encrypted cookies + Stripe SDK.'),
            $this->extension('fileinfo', 'Required by upload mime sniffing.'),
            $this->extension('zip', 'Required by template kit + export ZIPs.'),
            $this->extension('gd', 'Required by image manipulation; Imagick also acceptable.'),
            $this->writable(storage_path()),
            $this->writable(base_path('bootstrap/cache')),
            $this->envFile(),
            $this->appKey(),
        ];
    }

    public function allPass(): bool
    {
        foreach ($this->checks() as $check) {
            if (! $check['ok']) {
                return false;
            }
        }

        return true;
    }

    /** @return array{label: string, ok: bool, hint: string|null} */
    private function phpVersion(): array
    {
        // Pinned floor matches CLAUDE.md — 8.3 is the lowest version we
        // promise to support; 8.4 / 8.5 work but aren't required.
        $ok = version_compare(PHP_VERSION, '8.3.0', '>=');

        return [
            'label' => 'PHP 8.3 or higher (current: '.PHP_VERSION.')',
            'ok' => $ok,
            'hint' => $ok ? null : 'Switch your hosting account to PHP 8.3+ in the cPanel/hPanel.',
        ];
    }

    /** @return array{label: string, ok: bool, hint: string|null} */
    private function extension(string $name, string $why): array
    {
        $ok = extension_loaded($name) || ($name === 'gd' && extension_loaded('imagick'));

        return [
            'label' => "PHP extension: {$name}",
            'ok' => $ok,
            'hint' => $ok ? null : "{$why} Enable the extension in your hosting panel's PHP options.",
        ];
    }

    /** @return array{label: string, ok: bool, hint: string|null} */
    private function writable(string $path): array
    {
        $ok = is_dir($path) && is_writable($path);

        return [
            'label' => "Writable: {$path}",
            'ok' => $ok,
            'hint' => $ok ? null : "Set permissions to 775 (or 755 + correct owner) on this directory.",
        ];
    }

    /** @return array{label: string, ok: bool, hint: string|null} */
    private function envFile(): array
    {
        $ok = file_exists(base_path('.env'));

        return [
            'label' => '.env file present',
            'ok' => $ok,
            'hint' => $ok ? null : 'Copy .env.example to .env at the project root.',
        ];
    }

    /** @return array{label: string, ok: bool, hint: string|null} */
    private function appKey(): array
    {
        $key = (string) config('app.key');
        $ok = $key !== '' && str_starts_with($key, 'base64:');

        return [
            'label' => 'APP_KEY generated',
            'ok' => $ok,
            'hint' => $ok ? null : 'Run `php artisan key:generate` once via SSH, OR set APP_KEY manually in .env (32 random base64 bytes).',
        ];
    }
}
