<?php

namespace App\Services;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;

class ServerInfoService
{
    protected array $requiredExtensions = [
        ['name' => 'ctype', 'label' => 'Ctype', 'reason' => 'Laravel 框架核心依赖'],
        ['name' => 'curl', 'label' => 'cURL', 'reason' => '支付接口、HTTP 请求'],
        ['name' => 'fileinfo', 'label' => 'Fileinfo', 'reason' => '文件上传类型检测'],
        ['name' => 'filter', 'label' => 'Filter', 'reason' => 'Laravel 框架核心依赖'],
        ['name' => 'gd', 'label' => 'GD', 'reason' => '图片处理与缩略图'],
        ['name' => 'hash', 'label' => 'Hash', 'reason' => 'Laravel 框架核心依赖'],
        ['name' => 'json', 'label' => 'JSON', 'reason' => '数据序列化与API通信'],
        ['name' => 'mbstring', 'label' => 'Mbstring', 'reason' => 'Laravel 框架核心依赖'],
        ['name' => 'openssl', 'label' => 'OpenSSL', 'reason' => '加密、HTTPS、支付签名'],
        ['name' => 'pdo', 'label' => 'PDO', 'reason' => '数据库连接层'],
        ['name' => 'pdo_mysql', 'label' => 'PDO MySQL', 'reason' => 'MySQL 数据库驱动'],
        ['name' => 'session', 'label' => 'Session', 'reason' => 'Laravel 框架核心依赖'],
        ['name' => 'tokenizer', 'label' => 'Tokenizer', 'reason' => 'Laravel 框架核心依赖'],
        ['name' => 'zip', 'label' => 'Zip', 'reason' => '升级包与应用包处理'],
    ];

    public function getEnvironmentInfo(): array
    {
        $dbInfo = $this->getDatabaseInfo();
        $uploadDir = public_path('Uploads');

        return [
            'php_version' => PHP_VERSION,
            'mysql_version' => $dbInfo['version'],
            'db_record_count' => $dbInfo['record_count'],
            'db_data_size' => $dbInfo['data_size'],
            'db_index_size' => $dbInfo['index_size'],
            'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? '-',
            'upload_dir' => $uploadDir,
            'upload_dir_size' => $this->getDirectorySize($uploadDir),
            'upload_max_filesize' => ini_get('upload_max_filesize'),
            'max_execution_time' => ini_get('max_execution_time'),
            'session_gc_maxlifetime' => ini_get('session.gc_maxlifetime'),
            'default_socket_timeout' => ini_get('default_socket_timeout'),
            'memory_limit' => ini_get('memory_limit'),
            'post_max_size' => ini_get('post_max_size'),
        ];
    }

    public function getSystemInfo(): array
    {
        $rawKey = (string) config('apps.site_key', '');
        $maskedKey = $rawKey ? substr($rawKey, 0, 4) . str_repeat('*', max(0, strlen($rawKey) - 8)) . substr($rawKey, -4) : '';
        $host = $_SERVER['HTTP_HOST'] ?? '';

        return [
            'system_name' => 'CmsPro 内容管理系统',
            'system_version' => system_version(),
            'system_build' => system_build(),
            'framework' => 'Laravel ' . app()->version(),
            'php_os' => PHP_OS,
            'php_sapi' => php_sapi_name(),
            'timezone' => date_default_timezone_get(),
            'server_time' => date('Y-m-d H:i:s'),
            'host' => $host,
            'site_key' => $rawKey,
            'site_key_masked' => $maskedKey ?: '-',
        ];
    }

    public function getExtensionCheck(): array
    {
        $required = [];
        foreach ($this->requiredExtensions as $ext) {
            $required[] = [
                'name' => $ext['name'],
                'label' => $ext['label'],
                'reason' => $ext['reason'],
                'loaded' => extension_loaded($ext['name']),
            ];
        }

        $loaded = [];
        foreach (get_loaded_extensions() as $ext) {
            $loaded[] = $ext;
        }
        sort($loaded);

        $disabledFunctions = [];
        $disabledStr = ini_get('disable_functions');
        if ($disabledStr) {
            $disabledFunctions = explode(',', $disabledStr);
            $disabledFunctions = array_map('trim', $disabledFunctions);
            $disabledFunctions = array_filter($disabledFunctions);
        }

        return [
            'required' => $required,
            'all_loaded' => $loaded,
            'disabled_functions' => array_values($disabledFunctions),
            'all_required_loaded' => collect($required)->every(fn ($e) => $e['loaded']),
        ];
    }

    /**
     * 检测与中心服务器（v5.cmspro.cn）的通讯状态，同时返回当前域名的授权版本
     *
     * 客户端主动向中心服务器 /api/market/site/check 上报 site_key 和 domain，
     * 若中心服务器识别该站点则返回 registered: true，证明与服务端通讯正常。
     */
    public function checkServerCommunication(): array
    {
        $siteKey = (string) config('apps.site_key', '');
        $domain = $_SERVER['HTTP_HOST'] ?? '';

        // 本地查询当前域名的授权版本
        $licenseType = '免费版';
        if ($domain) {
            try {
                $license = \App\Apps\Cmsprohome\Models\License::byDomain($domain)->valid()->first();
                if ($license && $license->license_type) {
                    $licenseType = $license->license_type;
                }
            } catch (\Throwable) {
                // 授权表不存在或查询失败时静默降级
            }
        }

        $result = [
            'connected' => false,
            'message' => '缺少 site_key 或域名',
            'license_type' => $licenseType,
        ];

        if (!$siteKey || !$domain) {
            return $result;
        }

        try {
            $response = Http::timeout(8)->get('https://v5.cmspro.cn/api/market/site/check', [
                'site_key' => $siteKey,
                'domain' => $domain,
            ]);

            if ($response->successful()) {
                $data = $response->json();
                $registered = !empty($data['data']['registered']);
                $result['connected'] = $registered;
                $result['message'] = $registered ? '已连接' : '未注册';
                // 如果中心服务器返回了授权版本信息，优先使用
                if ($registered && !empty($data['data']['license_type'])) {
                    $result['license_type'] = $data['data']['license_type'];
                }
            } else {
                $result['message'] = '中心服务器未响应';
            }
        } catch (\Throwable $e) {
            $result['message'] = '连接失败: ' . $e->getMessage();
        }

        return $result;
    }

    protected function getDatabaseInfo(): array
    {
        try {
            $database = config('database.connections.mysql.database');
            $versionResult = DB::selectOne('SELECT VERSION() as ver');
            $version = $versionResult->ver ?? '-';

            $status = DB::selectOne(
                "SELECT SUM(table_rows) as row_count, SUM(data_length) as data_size, SUM(index_length) as index_size FROM information_schema.tables WHERE table_schema = ?",
                [$database]
            );

            return [
                'version' => $version,
                'record_count' => $status->row_count ? number_format($status->row_count) : '0',
                'data_size' => $status->data_size ? round($status->data_size / 1048576, 2) : '0',
                'index_size' => $status->index_size ? round($status->index_size / 1048576, 2) : '0',
            ];
        } catch (\Throwable) {
            return [
                'version' => '-',
                'record_count' => '0',
                'data_size' => '0',
                'index_size' => '0',
            ];
        }
    }

    protected function getDirectorySize(string $path): string
    {
        if (! is_dir($path)) {
            return '0 MB';
        }

        try {
            $size = 0;
            $iterator = new \RecursiveIteratorIterator(
                new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS)
            );
            foreach ($iterator as $file) {
                $size += $file->getSize();
            }

            if ($size >= 1073741824) {
                return round($size / 1073741824, 2) . ' GB';
            }

            return round($size / 1048576, 2) . ' MB';
        } catch (\Throwable) {
            return '0 MB';
        }
    }
}
