<?php

declare(strict_types=1);

namespace App\Framework\Mcp\Tools\Categories\Development;

use App\Framework\Attributes\McpTool;
use App\Framework\Config\Environment;
use App\Framework\Config\EnvKey;
use App\Framework\Core\ValueObjects\Byte;
use Psr\Log\LoggerInterface;

/**
 * MCP Tool for Hot Reload management in development
 */
final readonly class HotReloadTool
{
    public function __construct(
        private Environment $environment,
        private ?LoggerInterface $logger = null
    ) {
    }

    #[McpTool(
        name: 'dev_hot_reload_status',
        description: 'Check hot reload server status and configuration'
    )]
    public function getStatus(): array
    {
        // Check if in development mode
        $isDebugMode = $this->environment->getBool(EnvKey::APP_DEBUG, false);

        if (! $isDebugMode) {
            return [
                'enabled' => false,
                'reason' => 'Hot Reload is only available in development mode (APP_DEBUG=true)',
                'environment' => $this->environment->get(EnvKey::APP_ENV, 'production'),
            ];
        }

        // Check if hot reload process is running
        $pidFile = __DIR__ . '/../../../../var/hot-reload.pid';
        $isRunning = false;
        $pid = null;

        if (file_exists($pidFile)) {
            $pid = (int) file_get_contents($pidFile);
            // Check if process is actually running
            if ($pid > 0 && file_exists("/proc/{$pid}")) {
                $isRunning = true;
            }
        }

        return [
            'enabled' => true,
            'running' => $isRunning,
            'pid' => $pid,
            'endpoint' => '/dev/hot-reload',
            'configuration' => [
                'base_path' => dirname(__DIR__, 4),
                'poll_interval' => '500ms',
                'watch_patterns' => [
                    'src/**/*.php',
                    'resources/views/**/*.php',
                    'resources/views/**/*.view.php',
                    'config/**/*.php',
                ],
                'ignore_patterns' => [
                    'vendor/**',
                    'var/**',
                    'storage/**',
                    'tests/**',
                    'public/**',
                ],
            ],
            'cache_directories' => [
                'discovery' => $this->getCacheDirectoryInfo('var/cache/discovery'),
                'views' => $this->getCacheDirectoryInfo('var/cache/views'),
                'routes' => $this->getCacheDirectoryInfo('var/cache/routes'),
            ],
        ];
    }

    #[McpTool(
        name: 'dev_hot_reload_start',
        description: 'Start the hot reload server (development only)'
    )]
    public function start(): array
    {
        if (! $this->environment->getBool(EnvKey::APP_DEBUG, false)) {
            return [
                'success' => false,
                'error' => 'Hot Reload is only available in development mode',
                'hint' => 'Set APP_DEBUG=true in your .env file',
            ];
        }

        // Check if already running
        $status = $this->getStatus();
        if ($status['running'] ?? false) {
            return [
                'success' => false,
                'error' => 'Hot Reload server is already running',
                'pid' => $status['pid'],
            ];
        }

        // Create start script
        $scriptPath = __DIR__ . '/../../../../var/start-hot-reload.sh';
        $script = <<<'BASH'
#!/bin/bash
cd "$(dirname "$0")/.."
nohup php console.php dev:hot-reload > var/logs/hot-reload.log 2>&1 &
echo $! > var/hot-reload.pid
BASH;

        file_put_contents($scriptPath, $script);
        chmod($scriptPath, 0755);

        // Execute the script
        exec($scriptPath, $output, $returnCode);

        if ($returnCode === 0) {
            $pid = (int) file_get_contents(__DIR__ . '/../../../../var/hot-reload.pid');

            return [
                'success' => true,
                'message' => 'Hot Reload server started successfully',
                'pid' => $pid,
                'log_file' => 'var/logs/hot-reload.log',
                'endpoint' => '/dev/hot-reload',
            ];
        }

        return [
            'success' => false,
            'error' => 'Failed to start Hot Reload server',
            'output' => $output,
            'return_code' => $returnCode,
        ];
    }

    #[McpTool(
        name: 'dev_hot_reload_stop',
        description: 'Stop the hot reload server'
    )]
    public function stop(): array
    {
        $status = $this->getStatus();

        if (! ($status['running'] ?? false)) {
            return [
                'success' => false,
                'error' => 'Hot Reload server is not running',
            ];
        }

        $pid = $status['pid'];
        if ($pid > 0) {
            // Send SIGTERM to gracefully stop the process
            exec("kill -TERM {$pid}", $output, $returnCode);

            // Remove PID file
            $pidFile = __DIR__ . '/../../../../var/hot-reload.pid';
            if (file_exists($pidFile)) {
                unlink($pidFile);
            }

            return [
                'success' => true,
                'message' => 'Hot Reload server stopped',
                'pid' => $pid,
            ];
        }

        return [
            'success' => false,
            'error' => 'Could not stop Hot Reload server',
        ];
    }

    #[McpTool(
        name: 'dev_clear_caches',
        description: 'Clear development caches (discovery, views, routes)'
    )]
    public function clearCaches(): array
    {
        $cleared = [];
        $errors = [];

        // Clear discovery cache
        $discoveryCache = __DIR__ . '/../../../../var/cache/discovery';
        if (is_dir($discoveryCache)) {
            $files = glob("$discoveryCache/*");
            if ($files !== false) {
                $count = count($files);
                array_map('unlink', $files);
                $cleared['discovery'] = $count;
            }
        }

        // Clear view cache
        $viewCache = __DIR__ . '/../../../../var/cache/views';
        if (is_dir($viewCache)) {
            $files = glob("$viewCache/*");
            if ($files !== false) {
                $count = count($files);
                array_map('unlink', $files);
                $cleared['views'] = $count;
            }
        }

        // Clear route cache
        $routeCache = __DIR__ . '/../../../../var/cache/routes';
        if (is_dir($routeCache)) {
            $files = glob("$routeCache/*");
            if ($files !== false) {
                $count = count($files);
                array_map('unlink', $files);
                $cleared['routes'] = $count;
            }
        }

        // Clear compiled templates
        $compiledTemplates = __DIR__ . '/../../../../var/cache/templates';
        if (is_dir($compiledTemplates)) {
            $files = glob("$compiledTemplates/*");
            if ($files !== false) {
                $count = count($files);
                array_map('unlink', $files);
                $cleared['templates'] = $count;
            }
        }

        $totalFiles = array_sum($cleared);

        return [
            'success' => true,
            'message' => "Cleared {$totalFiles} cached files",
            'details' => $cleared,
            'errors' => $errors,
        ];
    }

    #[McpTool(
        name: 'dev_hot_reload_logs',
        description: 'Get recent hot reload server logs'
    )]
    public function getLogs(int $lines = 50): array
    {
        $logFile = __DIR__ . '/../../../../var/logs/hot-reload.log';

        if (! file_exists($logFile)) {
            return [
                'success' => false,
                'error' => 'Log file not found',
                'hint' => 'Start the hot reload server first',
            ];
        }

        // Get last N lines of the log file
        $logs = [];
        $file = new \SplFileObject($logFile, 'r');
        $file->seek(PHP_INT_MAX);
        $totalLines = $file->key();

        $startLine = max(0, $totalLines - $lines);
        $file->seek($startLine);

        while (! $file->eof()) {
            $line = $file->fgets();
            if (trim($line) !== '') {
                $logs[] = trim($line);
            }
        }

        return [
            'success' => true,
            'log_file' => $logFile,
            'total_lines' => $totalLines,
            'returned_lines' => count($logs),
            'logs' => $logs,
        ];
    }

    #[McpTool(
        name: 'dev_simulate_file_change',
        description: 'Simulate a file change for testing hot reload'
    )]
    public function simulateFileChange(string $type = 'php'): array
    {
        $testFile = match($type) {
            'css' => __DIR__ . '/../../../../resources/css/test-hot-reload.css',
            'js' => __DIR__ . '/../../../../resources/js/test-hot-reload.js',
            'view' => __DIR__ . '/../../../../resources/views/test-hot-reload.view.php',
            default => __DIR__ . '/../../../../src/test-hot-reload.php',
        };

        // Create or touch the test file
        $content = match($type) {
            'css' => "/* Hot reload test - " . date('Y-m-d H:i:s') . " */\n.hot-reload-test { color: red; }",
            'js' => "// Hot reload test - " . date('Y-m-d H:i:s') . "\nconsole.log('Hot reload test');",
            'view' => "<!-- Hot reload test - " . date('Y-m-d H:i:s') . " -->\n<div>Test</div>",
            default => "<?php\n// Hot reload test - " . date('Y-m-d H:i:s') . "\n",
        };

        file_put_contents($testFile, $content);

        return [
            'success' => true,
            'message' => "Test file created/updated",
            'file' => $testFile,
            'type' => $type,
            'timestamp' => date('c'),
            'expected_reload' => match($type) {
                'css' => 'CSS hot replacement (no page reload)',
                'js' => 'HMR if supported, otherwise full reload',
                'view', 'php' => 'Full page reload',
                default => 'Full page reload',
            },
        ];
    }

    /**
     * Get cache directory information
     */
    private function getCacheDirectoryInfo(string $relativePath): array
    {
        $fullPath = dirname(__DIR__, 4) . '/' . $relativePath;

        if (! is_dir($fullPath)) {
            return [
                'exists' => false,
                'path' => $relativePath,
            ];
        }

        $files = glob("$fullPath/*");
        $fileCount = $files ? count($files) : 0;
        $totalSize = 0;

        if ($files) {
            foreach ($files as $file) {
                if (is_file($file)) {
                    $totalSize += filesize($file);
                }
            }
        }

        return [
            'exists' => true,
            'path' => $relativePath,
            'files' => $fileCount,
            'size' => Byte::fromBytes($totalSize)->toHumanReadable(),
            'writable' => is_writable($fullPath),
        ];
    }
}
