<?php

namespace App\Support;

class Installer
{
    public const LOCK_FILE = 'app/installed.lock';

    /**
     * @return array<int, array<string, mixed>>
     */
    public static function environmentChecks(): array
    {
        $phpVersion = PHP_VERSION;
        $requiredVersion = '8.3.0';

        $checks = [
            [
                'key' => 'php_version',
                'label' => "PHP >= {$requiredVersion}",
                'ok' => version_compare($phpVersion, $requiredVersion, '>='),
                'details' => "Current: {$phpVersion}",
            ],
            [
                'key' => 'ext_openssl',
                'label' => 'OpenSSL extension',
                'ok' => extension_loaded('openssl'),
                'details' => null,
            ],
            [
                'key' => 'ext_pdo',
                'label' => 'PDO extension',
                'ok' => extension_loaded('pdo'),
                'details' => null,
            ],
            [
                'key' => 'ext_mbstring',
                'label' => 'Mbstring extension',
                'ok' => extension_loaded('mbstring'),
                'details' => null,
            ],
            [
                'key' => 'ext_tokenizer',
                'label' => 'Tokenizer extension',
                'ok' => extension_loaded('tokenizer'),
                'details' => null,
            ],
            [
                'key' => 'ext_xml',
                'label' => 'XML extension',
                'ok' => extension_loaded('xml'),
                'details' => null,
            ],
            [
                'key' => 'ext_ctype',
                'label' => 'Ctype extension',
                'ok' => extension_loaded('ctype'),
                'details' => null,
            ],
            [
                'key' => 'ext_json',
                'label' => 'JSON extension',
                'ok' => extension_loaded('json'),
                'details' => null,
            ],
            [
                'key' => 'ext_fileinfo',
                'label' => 'Fileinfo extension',
                'ok' => extension_loaded('fileinfo'),
                'details' => null,
            ],
            [
                'key' => 'ext_bcmath',
                'label' => 'BCMath extension',
                'ok' => extension_loaded('bcmath'),
                'details' => null,
            ],
            [
                'key' => 'storage_writable',
                'label' => 'storage directory writable',
                'ok' => is_writable(storage_path()),
                'details' => storage_path(),
            ],
            [
                'key' => 'cache_writable',
                'label' => 'bootstrap/cache writable',
                'ok' => is_writable(base_path('bootstrap/cache')),
                'details' => base_path('bootstrap/cache'),
            ],
            [
                'key' => 'env_writable',
                'label' => '.env writable or creatable',
                'ok' => self::isEnvWritable(),
                'details' => base_path('.env'),
            ],
        ];

        return $checks;
    }

    public static function passesEnvironmentChecks(): bool
    {
        return collect(self::environmentChecks())->every(fn (array $check): bool => (bool) $check['ok']);
    }

    public static function isInstalled(): bool
    {
        // Lock file is the source of truth to avoid false positives
        // when a preconfigured .env is accidentally uploaded.
        return file_exists(storage_path(self::LOCK_FILE));
    }

    public static function markInstalled(): void
    {
        $path = storage_path(self::LOCK_FILE);
        $directory = dirname($path);

        if (! is_dir($directory)) {
            mkdir($directory, 0755, true);
        }

        file_put_contents($path, now()->toIso8601String());
    }

    private static function isEnvWritable(): bool
    {
        $envPath = base_path('.env');
        if (file_exists($envPath)) {
            return is_writable($envPath);
        }

        return is_writable(base_path());
    }
}
