<?php

declare(strict_types=1);

namespace App\Application\Admin\System\Service;

use App\Framework\Core\ValueObjects\Byte;

final readonly class PhpInfoService
{
    public function getStructuredInfo(): array
    {
        return [
            'general' => $this->getGeneralInfo(),
            'configuration' => $this->getConfigurationInfo(),
            'extensions' => $this->getExtensionsInfo(),
            'environment' => $this->getEnvironmentInfo(),
        ];
    }

    private function getGeneralInfo(): array
    {
        return [
            'version' => PHP_VERSION,
            'sapi' => PHP_SAPI,
            'os' => PHP_OS,
            'architecture' => php_uname('m'),
            'build_date' => phpversion(),
            'compiler' => defined('PHP_COMPILER') ? PHP_COMPILER : 'Unknown',
            'configure_command' => php_uname('v'),
        ];
    }

    private function getConfigurationInfo(): array
    {
        $memoryLimit = ini_get('memory_limit');
        $uploadMaxSize = ini_get('upload_max_filesize');
        $postMaxSize = ini_get('post_max_size');

        return [
            'memory_limit' => $memoryLimit,
            'memory_limit_bytes' => $this->parseMemorySize($memoryLimit),
            'max_execution_time' => ini_get('max_execution_time'),
            'max_input_time' => ini_get('max_input_time'),
            'upload_max_filesize' => $uploadMaxSize,
            'upload_max_filesize_bytes' => $this->parseMemorySize($uploadMaxSize),
            'post_max_size' => $postMaxSize,
            'post_max_size_bytes' => $this->parseMemorySize($postMaxSize),
            'max_file_uploads' => ini_get('max_file_uploads'),
            'display_errors' => ini_get('display_errors') ? 'On' : 'Off',
            'log_errors' => ini_get('log_errors') ? 'On' : 'Off',
            'error_reporting' => $this->getErrorReportingLevel(),
            'timezone' => ini_get('date.timezone') ?: 'Not set',
        ];
    }

    private function getExtensionsInfo(): array
    {
        $extensions = get_loaded_extensions();
        sort($extensions);

        $extensionDetails = [];
        foreach ($extensions as $extension) {
            $extensionDetails[] = [
                'name' => $extension,
                'version' => phpversion($extension) ?: 'Unknown',
                'functions' => count(get_extension_funcs($extension) ?: []),
            ];
        }

        return [
            'count' => count($extensions),
            'list' => $extensions,
            'details' => $extensionDetails,
        ];
    }

    private function getEnvironmentInfo(): array
    {
        return [
            'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown',
            'document_root' => $_SERVER['DOCUMENT_ROOT'] ?? 'Unknown',
            'server_admin' => $_SERVER['SERVER_ADMIN'] ?? 'Not set',
            'server_name' => $_SERVER['SERVER_NAME'] ?? 'Unknown',
            'server_port' => $_SERVER['SERVER_PORT'] ?? 'Unknown',
            'request_time' => date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME'] ?? time()),
            'https' => isset($_SERVER['HTTPS']) ? 'On' : 'Off',
        ];
    }

    private function parseMemorySize(string $size): ?Byte
    {
        if ($size === '-1') {
            return null; // Unlimited
        }

        $value = (int) $size;
        $unit = strtolower($size[strlen($size) - 1] ?? '');

        $bytes = match ($unit) {
            'k' => $value * 1024,
            'm' => $value * 1024 * 1024,
            'g' => $value * 1024 * 1024 * 1024,
            default => $value,
        };

        return Byte::fromBytes($bytes);
    }

    private function getErrorReportingLevel(): string
    {
        $level = error_reporting();

        $levels = [
            E_ERROR => 'E_ERROR',
            E_WARNING => 'E_WARNING',
            E_PARSE => 'E_PARSE',
            E_NOTICE => 'E_NOTICE',
            E_CORE_ERROR => 'E_CORE_ERROR',
            E_CORE_WARNING => 'E_CORE_WARNING',
            E_COMPILE_ERROR => 'E_COMPILE_ERROR',
            E_COMPILE_WARNING => 'E_COMPILE_WARNING',
            E_USER_ERROR => 'E_USER_ERROR',
            E_USER_WARNING => 'E_USER_WARNING',
            E_USER_NOTICE => 'E_USER_NOTICE',
            E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
            E_DEPRECATED => 'E_DEPRECATED',
            E_USER_DEPRECATED => 'E_USER_DEPRECATED',
        ];

        if ($level === E_ALL) {
            return 'E_ALL';
        }

        $enabledLevels = [];
        foreach ($levels as $value => $name) {
            if ($level & $value) {
                $enabledLevels[] = $name;
            }
        }

        return implode(' | ', $enabledLevels) ?: 'None';
    }
}
