<?php

declare(strict_types=1);

require_once __DIR__ . '/../../vendor/autoload.php';

use App\Framework\Core\Events\AfterControllerExecution;
use App\Framework\Core\Events\AfterHandleRequest;
use App\Framework\Core\Events\AfterMiddlewareExecution;
use App\Framework\Core\Events\AfterRouteMatching;
use App\Framework\Core\Events\BeforeControllerExecution;
use App\Framework\Core\Events\BeforeHandleRequest;
use App\Framework\Core\Events\BeforeMiddlewareExecution;
use App\Framework\Core\Events\BeforeRouteMatching;
use App\Framework\Core\ValueObjects\ClassName;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Core\ValueObjects\MethodName;
use App\Framework\Core\ValueObjects\Timestamp;
use App\Framework\Http\Request;
use App\Framework\Http\Response;

echo "=== Testing Request Lifecycle Hooks ===\n\n";

echo "1. Testing Enhanced Lifecycle Events with Value Objects:\n";

try {
    // Mock request and response for testing
    $mockRequest = new class () {
        public $path;

        public $method;

        public $server;

        public function __construct()
        {
            $this->path = new class () {
                public function toString(): string
                {
                    return '/test';
                }
            };
            $this->method = new class () {
                public $value = 'GET';
            };
            $this->server = new class () {
                public function getUserAgent()
                {
                    return new class () {
                        public function toString(): string
                        {
                            return 'Test Agent';
                        }
                    };
                }

                public function getClientIp()
                {
                    return new class () {
                        public function __toString(): string
                        {
                            return '127.0.0.1';
                        }
                    };
                }
            };
        }
    };

    $mockResponse = new class () {
        public $statusCode = 200;

        public $body = 'Test Response';

        public $headers = ['Content-Type' => 'text/html'];
    };

    echo "   ✅ Testing BeforeHandleRequest Event:\n";
    $beforeEvent = new BeforeHandleRequest(
        request: $mockRequest,
        context: [
            'route' => '/test',
            'method' => 'GET',
            'user_agent' => 'Test Agent',
            'client_ip' => '127.0.0.1',
        ]
    );
    echo "      • Timestamp: {$beforeEvent->timestamp->format('H:i:s.u')}\n";
    echo "      • Context keys: " . implode(', ', array_keys($beforeEvent->context)) . "\n\n";

    echo "   ✅ Testing AfterHandleRequest Event:\n";
    $afterEvent = new AfterHandleRequest(
        request: $mockRequest,
        response: $mockResponse,
        processingTime: Duration::fromMilliseconds(45.7),
        context: [
            'status_code' => 200,
            'content_length' => 13,
            'memory_peak' => 1024000,
        ]
    );
    echo "      • Processing time: {$afterEvent->processingTime->toHumanReadable()}\n";
    echo "      • Timestamp: {$afterEvent->timestamp->format('H:i:s.u')}\n\n";

    echo "   ✅ Testing BeforeRouteMatching Event:\n";
    $routeBeforeEvent = new BeforeRouteMatching(
        request: $mockRequest,
        context: ['pattern_count' => 25]
    );
    echo "      • Timestamp: {$routeBeforeEvent->timestamp->format('H:i:s.u')}\n";

    echo "   ✅ Testing AfterRouteMatching Event:\n";
    $routeAfterEvent = new AfterRouteMatching(
        request: $mockRequest,
        routeName: 'api.users.show',
        routeParameters: ['id' => '123'],
        matchingTime: Duration::fromMicroseconds(150),
        context: ['matched_patterns' => 3]
    );
    echo "      • Route name: {$routeAfterEvent->routeName}\n";
    echo "      • Matching time: {$routeAfterEvent->matchingTime->toHumanReadable()}\n";
    echo "      • Parameters: " . json_encode($routeAfterEvent->routeParameters) . "\n\n";

    echo "   ✅ Testing BeforeControllerExecution Event:\n";
    $controllerBeforeEvent = new BeforeControllerExecution(
        request: $mockRequest,
        controllerClass: ClassName::create('App\\Application\\Api\\UserController'),
        methodName: MethodName::create('show'),
        parameters: ['id' => '123'],
        context: ['auth_user' => 'user_456']
    );
    echo "      • Controller: {$controllerBeforeEvent->controllerClass->getShortName()}\n";
    echo "      • Method: {$controllerBeforeEvent->methodName->toString()}\n";
    echo "      • Parameters: " . json_encode($controllerBeforeEvent->parameters) . "\n\n";

    echo "   ✅ Testing AfterControllerExecution Event:\n";
    $controllerAfterEvent = new AfterControllerExecution(
        request: $mockRequest,
        response: $mockResponse,
        controllerClass: ClassName::create('App\\Application\\Api\\UserController'),
        methodName: MethodName::create('show'),
        executionTime: Duration::fromMilliseconds(23.4),
        context: ['db_queries' => 2, 'cache_hits' => 1]
    );
    echo "      • Execution time: {$controllerAfterEvent->executionTime->toHumanReadable()}\n";
    echo "      • DB queries: {$controllerAfterEvent->context['db_queries']}\n\n";

    echo "   ✅ Testing BeforeMiddlewareExecution Event:\n";
    $middlewareBeforeEvent = new BeforeMiddlewareExecution(
        request: $mockRequest,
        middlewareClass: ClassName::create('App\\Framework\\Http\\Middlewares\\AuthMiddleware'),
        priority: 100,
        context: ['middleware_chain_position' => 2]
    );
    echo "      • Middleware: {$middlewareBeforeEvent->middlewareClass->getShortName()}\n";
    echo "      • Priority: {$middlewareBeforeEvent->priority}\n\n";

    echo "   ✅ Testing AfterMiddlewareExecution Event:\n";
    $middlewareAfterEvent = new AfterMiddlewareExecution(
        request: $mockRequest,
        response: $mockResponse,
        middlewareClass: ClassName::create('App\\Framework\\Http\\Middlewares\\AuthMiddleware'),
        executionTime: Duration::fromMicroseconds(850),
        context: ['auth_checks' => 1, 'headers_added' => 2]
    );
    echo "      • Execution time: {$middlewareAfterEvent->executionTime->toHumanReadable()}\n";
    echo "      • Headers added: {$middlewareAfterEvent->context['headers_added']}\n\n";

} catch (\Throwable $e) {
    echo "   ❌ Error: {$e->getMessage()}\n\n";
}

echo "2. Testing Timestamp and Duration Value Objects:\n";

try {
    $start = Timestamp::now();
    usleep(1000); // 1ms delay
    $end = Timestamp::now();

    $duration = $start->diff($end);

    echo "   ✅ Timestamp calculations:\n";
    echo "      • Start: {$start->format('H:i:s.u')}\n";
    echo "      • End: {$end->format('H:i:s.u')}\n";
    echo "      • Duration: {$duration->toHumanReadable()}\n";
    echo "      • Duration (microseconds): {$duration->toMicroseconds()}\n\n";

    echo "   ✅ Duration factory methods:\n";
    $durations = [
        'Microseconds' => Duration::fromMicroseconds(500),
        'Milliseconds' => Duration::fromMilliseconds(45.7),
        'Seconds' => Duration::fromSeconds(2.5),
        'Minutes' => Duration::fromMinutes(1.5),
    ];

    foreach ($durations as $type => $duration) {
        echo "      • {$type}: {$duration->toHumanReadable()}\n";
    }
    echo "\n";

} catch (\Throwable $e) {
    echo "   ❌ Error: {$e->getMessage()}\n\n";
}

echo "3. Testing ClassName and MethodName Value Objects:\n";

try {
    $className = ClassName::create('App\\Framework\\Http\\Middlewares\\AuthenticationMiddleware');
    $methodName = MethodName::create('handle');

    echo "   ✅ ClassName operations:\n";
    echo "      • Full name: {$className->getFullyQualified()}\n";
    echo "      • Short name: {$className->getShortName()}\n";
    echo "      • Namespace: {$className->getNamespace()}\n\n";

    echo "   ✅ MethodName operations:\n";
    echo "      • Method name: {$methodName->toString()}\n";
    echo "      • Is magic method: " . ($methodName->isMagicMethod() ? 'Yes' : 'No') . "\n\n";

    $magicMethod = MethodName::construct();
    echo "   ✅ Magic method example:\n";
    echo "      • Method: {$magicMethod->toString()}\n";
    echo "      • Is magic: " . ($magicMethod->isMagicMethod() ? 'Yes' : 'No') . "\n\n";

} catch (\Throwable $e) {
    echo "   ❌ Error: {$e->getMessage()}\n\n";
}

echo "=== Request Lifecycle Hooks Test Completed ===\n";
