<?php

declare(strict_types=1);

namespace App\Framework\Context;

use App\Framework\Config\Environment;
use App\Framework\Config\EnvKey;
use App\Framework\Http\ServerEnvironment;

final readonly class ExecutionContext
{
    private ServerEnvironment $serverEnvironment;

    public function __construct(
        private ContextType $type,
        /** @var array<string, mixed> $metadata */
        private array $metadata = []
    ) {
        $this->serverEnvironment = ServerEnvironment::fromGlobals();
    }

    public function getType(): ContextType
    {
        return $this->type;
    }

    public function isWeb(): bool
    {
        return $this->type === ContextType::WEB;
    }

    public function isWorker(): bool
    {
        return $this->type === ContextType::WORKER;
    }

    public function isConsole(): bool
    {
        return $this->type === ContextType::CONSOLE;
    }

    public function isCli(): bool
    {
        return in_array($this->type, [
            ContextType::CONSOLE,
            ContextType::WORKER,
            ContextType::CLI_SCRIPT,
        ]);
    }

    public function isTest(): bool
    {
        return $this->type === ContextType::TEST;
    }

    /**
     * @return array<string, mixed>
     */
    public function getMetadata(): array
    {
        return array_merge([
            'type' => $this->type->value,
            'sapi' => php_sapi_name(),
            'script' => $_SERVER['argv'][0] ?? null,
            'command_line' => implode(' ', $_SERVER['argv'] ?? []),
            'pid' => getmypid(),
        ], $this->metadata);
    }

    public static function detect(?Environment $environment = null): self
    {
        #$environment->get(EnvKey::APP_ENV);

        // Debug logging
        #error_log("ExecutionContext::detect() - SAPI: " . php_sapi_name());
        #error_log("ExecutionContext::detect() - REQUEST_METHOD: " . ($_SERVER['REQUEST_METHOD'] ?? 'not set'));
        #error_log("ExecutionContext::detect() - HTTP_HOST: " . ($_SERVER['HTTP_HOST'] ?? 'not set'));
        #error_log("ExecutionContext::detect() - SERVER_NAME: " . ($_SERVER['SERVER_NAME'] ?? 'not set'));

        // Test Environment
        if (defined('PHPUNIT_COMPOSER_INSTALL') ||
            isset($_ENV['APP_ENV']) && $_ENV['APP_ENV'] === 'testing') {
            return new self(ContextType::TEST, ['detected_by' => 'phpunit_or_env']);
        }

        // Web Request - Robustere Detection für Docker/nginx/php-fpm
        if (php_sapi_name() !== 'cli' ||
            isset($_SERVER['REQUEST_METHOD']) ||
            isset($_SERVER['HTTP_HOST']) ||
            isset($_SERVER['SERVER_NAME'])) {
            return new self(ContextType::WEB, ['detected_by' => 'sapi_or_http_vars', 'sapi' => php_sapi_name()]);
        }

        // CLI Detection
        $scriptName = $_SERVER['argv'][0] ?? '';
        $commandLine = implode(' ', $_SERVER['argv'] ?? []);

        $type = match(true) {
            str_contains($scriptName, 'worker') => ContextType::WORKER,
            // Temporarily treat console.php as CLI_SCRIPT until CONSOLE context discovery is fixed
            // str_contains($scriptName, 'console') => ContextType::CONSOLE,
            str_contains($commandLine, 'pest') => ContextType::TEST,
            str_contains($commandLine, 'phpunit') => ContextType::TEST,
            default => ContextType::CLI_SCRIPT
        };

        return new self($type, [
            'detected_by' => 'cli_analysis',
            'script_name' => $scriptName,
            'command_line' => $commandLine,
        ]);
    }

    public static function forWorker(): self
    {
        return new self(ContextType::WORKER, ['forced_by' => 'worker']);
    }

    public static function forTest(): self
    {
        return new self(ContextType::TEST, ['forced_by' => 'test']);
    }

    public static function forConsole(): self
    {
        return new self(ContextType::CONSOLE, ['forced_by' => 'console']);
    }

    public static function forWeb(): self
    {
        return new self(ContextType::WEB, ['forced_by' => 'web']);
    }
}
