<?php

declare(strict_types=1);

namespace App\Modules\Developer;

use App\Core\Database;

/**
 * SystemHealthService — System Diagnostics & Health Inspections
 *
 * Performs comprehensive environment health checks for DX003:
 *   - Database Connection (MySQL)
 *   - Supabase Connection & Configuration
 *   - Storage Permissions (uploads, cache, logs, exports, sessions)
 *   - Core Directories
 *   - Required & Optional PHP Extensions
 *   - PHP Environment Limits & Memory Settings
 *
 * Returns structured health reports with status: 'healthy' | 'warning' | 'error'
 * and actionable recommendations for any non-healthy checks.
 *
 * @package Inveetaire
 * @ref     DX003
 */
class SystemHealthService
{
    private SupabaseService $supabaseService;

    public function __construct()
    {
        $this->supabaseService = new SupabaseService();
    }

    /**
     * Run full system health diagnostic suite.
     *
     * @return array{
     *   overall_status: 'healthy'|'warning'|'error',
     *   overall_label: string,
     *   summary: array{healthy_count: int, warning_count: int, error_count: int, total_checks: int},
     *   checks: list<array{
     *     key: string,
     *     title: string,
     *     category: string,
     *     status: 'healthy'|'warning'|'error',
     *     value: string,
     *     recommendation: string|null
     *   }>,
     *   environment: array
     * }
     */
    public function inspectHealth(): array
    {
        $checks = [];

        // 1. Database Connection
        $checks[] = $this->checkDatabaseConnection();

        // 2. Supabase Connection & Mirror Status
        $checks[] = $this->checkSupabaseConnection();

        // 3. Storage Permissions
        $checks[] = $this->checkStoragePermissions();

        // 4. Log Directory
        $checks[] = $this->checkDirectory('storage_logs', 'Log Directory', ROOT_PATH . '/storage/logs');

        // 5. Cache Directory
        $checks[] = $this->checkDirectory('storage_cache', 'Cache Directory', ROOT_PATH . '/storage/cache');

        // 6. PHP Extensions
        $checks[] = $this->checkPhpExtensions();

        // 7. PHP Memory Limit
        $checks[] = $this->checkPhpMemoryLimit();

        // 8. Upload Limits
        $checks[] = $this->checkUploadLimits();

        // 9. Execution Time Limit
        $checks[] = $this->checkExecutionTimeLimit();

        // Summarize counts
        $healthyCount = 0;
        $warningCount = 0;
        $errorCount   = 0;

        foreach ($checks as $check) {
            if ($check['status'] === 'healthy') {
                $healthyCount++;
            } elseif ($check['status'] === 'warning') {
                $warningCount++;
            } else {
                $errorCount++;
            }
        }

        if ($errorCount > 0) {
            $overallStatus = 'error';
            $overallLabel  = 'System Issues Detected';
        } elseif ($warningCount > 0) {
            $overallStatus = 'warning';
            $overallLabel  = 'System Warnings Detected';
        } else {
            $overallStatus = 'healthy';
            $overallLabel  = 'All Systems Healthy';
        }

        return [
            'overall_status' => $overallStatus,
            'overall_label'  => $overallLabel,
            'summary'        => [
                'healthy_count' => $healthyCount,
                'warning_count' => $warningCount,
                'error_count'   => $errorCount,
                'total_checks'  => count($checks),
            ],
            'checks'      => $checks,
            'environment' => [
                'php_version' => PHP_VERSION,
                'os'          => PHP_OS_FAMILY,
                'sapi'        => PHP_SAPI,
                'app_env'     => config('app.env', 'local'),
                'dev_mode'    => config('app.developer_mode', true) ? 'Enabled' : 'Disabled',
            ],
        ];
    }

    // ─────────────────────────────────────────────────────────────────────────
    // Individual Check Generators
    // ─────────────────────────────────────────────────────────────────────────

    private function checkDatabaseConnection(): array
    {
        try {
            $start = microtime(true);
            $pdo   = Database::getConnection();
            $pdo->query('SELECT 1');
            $latencyMs = round((microtime(true) - $start) * 1000, 2);

            $dbVersion = (string) $pdo->query('SELECT @@version')->fetchColumn();

            return [
                'key'            => 'database_connection',
                'title'          => 'Database Connection (MySQL)',
                'category'       => 'Infrastructure',
                'status'         => 'healthy',
                'value'          => "Connected ({$dbVersion}, {$latencyMs} ms)",
                'recommendation' => null,
            ];
        } catch (\Throwable $e) {
            return [
                'key'            => 'database_connection',
                'title'          => 'Database Connection (MySQL)',
                'category'       => 'Infrastructure',
                'status'         => 'error',
                'value'          => 'Disconnected / Error',
                'recommendation' => 'Check MySQL server status in XAMPP control panel and verify database credentials in .env.',
            ];
        }
    }

    private function checkSupabaseConnection(): array
    {
        if (!$this->supabaseService->isConfigured()) {
            return [
                'key'            => 'supabase_connection',
                'title'          => 'Supabase Connection',
                'category'       => 'Cloud Mirror',
                'status'         => 'warning',
                'value'          => 'Not Configured',
                'recommendation' => 'Supabase credentials are missing in .env. Configure SUPABASE_URL and SUPABASE_ANON_KEY to enable cloud mirror.',
            ];
        }

        $test = $this->supabaseService->testConnection();
        if ($test['connected'] ?? false) {
            return [
                'key'            => 'supabase_connection',
                'title'          => 'Supabase Connection',
                'category'       => 'Cloud Mirror',
                'status'         => 'healthy',
                'value'          => 'Connected (' . ($test['response_time_ms'] ?? 0) . ' ms)',
                'recommendation' => null,
            ];
        }

        return [
            'key'            => 'supabase_connection',
            'title'          => 'Supabase Connection',
            'category'       => 'Cloud Mirror',
            'status'         => 'error',
            'value'          => 'Connection Failed',
            'recommendation' => 'Verify SUPABASE_URL and SUPABASE_ANON_KEY. Check internet connectivity and outbound HTTPS access.',
        ];
    }

    private function checkStoragePermissions(): array
    {
        $baseStorage = ROOT_PATH . '/storage';
        if (!is_dir($baseStorage)) {
            @mkdir($baseStorage, 0755, true);
        }

        $isWritable = is_writable($baseStorage);

        if ($isWritable) {
            return [
                'key'            => 'storage_permissions',
                'title'          => 'Storage Permission',
                'category'       => 'File System',
                'status'         => 'healthy',
                'value'          => 'Writable (' . realpath($baseStorage) . ')',
                'recommendation' => null,
            ];
        }

        return [
            'key'            => 'storage_permissions',
            'title'          => 'Storage Permission',
            'category'       => 'File System',
            'status'         => 'error',
            'value'          => 'Read-Only / Permission Denied',
            'recommendation' => 'Grant write permissions to the storage directory (chmod -R 775 storage or check Windows permissions).',
        ];
    }

    private function checkDirectory(string $key, string $title, string $path): array
    {
        if (!is_dir($path)) {
            @mkdir($path, 0755, true);
        }

        $exists   = is_dir($path);
        $writable = $exists && is_writable($path);

        if ($exists && $writable) {
            return [
                'key'            => $key,
                'title'          => $title,
                'category'       => 'File System',
                'status'         => 'healthy',
                'value'          => 'Available & Writable',
                'recommendation' => null,
            ];
        }

        return [
            'key'            => $key,
            'title'          => $title,
            'category'       => 'File System',
            'status'         => 'error',
            'value'          => $exists ? 'Not Writable' : 'Missing Directory',
            'recommendation' => "Ensure directory {$path} exists and is writeable by the web server process.",
        ];
    }

    private function checkPhpExtensions(): array
    {
        $required = ['pdo', 'pdo_mysql', 'curl', 'json', 'mbstring', 'openssl', 'fileinfo'];
        $missing  = [];

        foreach ($required as $ext) {
            if (!extension_loaded($ext)) {
                $missing[] = $ext;
            }
        }

        $hasPgsql = extension_loaded('pdo_pgsql') || extension_loaded('pgsql');

        if (!empty($missing)) {
            return [
                'key'            => 'php_extensions',
                'title'          => 'PHP Extensions',
                'category'       => 'Environment',
                'status'         => 'error',
                'value'          => 'Missing: ' . implode(', ', $missing),
                'recommendation' => 'Enable the required extension(s) in php.ini: ' . implode(', ', $missing),
            ];
        }

        if (!$hasPgsql) {
            return [
                'key'            => 'php_extensions',
                'title'          => 'PHP Extensions',
                'category'       => 'Environment',
                'status'         => 'warning',
                'value'          => 'Required OK (pdo_pgsql disabled — SQL Export Mode active)',
                'recommendation' => 'pdo_pgsql extension is disabled in XAMPP php.ini. DX002B uses Supabase Management API or SQL Export Mode.',
            ];
        }

        return [
            'key'            => 'php_extensions',
            'title'          => 'PHP Extensions',
            'category'       => 'Environment',
            'status'         => 'healthy',
            'value'          => 'All Core Extensions Loaded',
            'recommendation' => null,
        ];
    }

    private function checkPhpMemoryLimit(): array
    {
        $limit = ini_get('memory_limit');
        $bytes = $this->parseBytes($limit);

        // >= 128MB is healthy, < 128MB warning, < 64MB error
        if ($bytes >= 128 * 1024 * 1024 || $limit === '-1') {
            return [
                'key'            => 'php_memory_limit',
                'title'          => 'PHP Memory Limit',
                'category'       => 'Resource Limits',
                'status'         => 'healthy',
                'value'          => $limit === '-1' ? 'Unlimited' : $limit,
                'recommendation' => null,
            ];
        }

        if ($bytes >= 64 * 1024 * 1024) {
            return [
                'key'            => 'php_memory_limit',
                'title'          => 'PHP Memory Limit',
                'category'       => 'Resource Limits',
                'status'         => 'warning',
                'value'          => $limit . ' (Recommended: 128M+)',
                'recommendation' => 'Increase memory_limit to 128M or higher in php.ini for optimal schema generation performance.',
            ];
        }

        return [
            'key'            => 'php_memory_limit',
            'title'          => 'PHP Memory Limit',
            'category'       => 'Resource Limits',
            'status'         => 'error',
            'value'          => $limit . ' (Critically Low)',
            'recommendation' => 'Set memory_limit = 128M in php.ini to prevent out-of-memory errors during export operations.',
        ];
    }

    private function checkUploadLimits(): array
    {
        $maxUpload = ini_get('upload_max_filesize');
        $maxPost   = ini_get('post_max_size');

        return [
            'key'            => 'upload_limits',
            'title'          => 'Upload & Post Limit',
            'category'       => 'Resource Limits',
            'status'         => 'healthy',
            'value'          => "Upload: {$maxUpload} | Post: {$maxPost}",
            'recommendation' => null,
        ];
    }

    private function checkExecutionTimeLimit(): array
    {
        $maxExec = ini_get('max_execution_time');
        $sec     = (int) $maxExec;

        if ($sec === 0 || $sec >= 30) {
            return [
                'key'            => 'execution_time_limit',
                'title'          => 'Execution Time Limit',
                'category'       => 'Resource Limits',
                'status'         => 'healthy',
                'value'          => $sec === 0 ? 'Unlimited (0s)' : "{$sec} seconds",
                'recommendation' => null,
            ];
        }

        return [
            'key'            => 'execution_time_limit',
            'title'          => 'Execution Time Limit',
            'category'       => 'Resource Limits',
            'status'         => 'warning',
            'value'          => "{$sec} seconds (Low)",
            'recommendation' => 'Increase max_execution_time to 30s or higher in php.ini for long-running schema inspections.',
        ];
    }

    private function parseBytes(string $value): int
    {
        $value = trim($value);
        if ($value === '' || $value === '-1') {
            return -1;
        }

        $last = strtolower($value[strlen($value) - 1]);
        $val  = (int) $value;

        switch ($last) {
            case 'g': $val *= 1024 * 1024 * 1024; break;
            case 'm': $val *= 1024 * 1024; break;
            case 'k': $val *= 1024; break;
        }

        return $val;
    }
}
