<?php

declare(strict_types=1);

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

use App\Framework\Core\ValueObjects\ClassName;
use App\Framework\Discovery\ValueObjects\DependencyEdge;
use App\Framework\Discovery\ValueObjects\DependencyGraph;
use App\Framework\Discovery\ValueObjects\DependencyNode;
use App\Framework\Discovery\ValueObjects\DependencyRelation;
use App\Framework\Discovery\ValueObjects\DependencyType;

echo "=== Testing Dependency Graph Value Objects ===\n\n";

echo "1. Testing DependencyNode creation:\n";

try {
    $className = ClassName::create('App\\Framework\\Router\\ValueObjects\\RoutePath');
    $type = DependencyType::VALUE_OBJECT;

    $node = DependencyNode::create($className, $type);

    echo "   ✅ Created dependency node:\n";
    echo "      • Class: {$node->getClassName()->toString()}\n";
    echo "      • Type: {$node->getType()->value}\n";
    echo "      • Complexity: {$node->getComplexityScore()}\n";
    echo "      • Is leaf: " . ($node->isLeaf() ? 'Yes' : 'No') . "\n";
    echo "      • Is root: " . ($node->isRoot() ? 'Yes' : 'No') . "\n\n";

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

echo "2. Testing DependencyEdge creation:\n";

try {
    $source = ClassName::create('App\\Framework\\Router\\ValueObjects\\RouteGroup');
    $target = ClassName::create('App\\Framework\\Router\\ValueObjects\\RoutePath');
    $relation = DependencyRelation::CONSTRUCTOR_INJECTION;

    $edge = DependencyEdge::create($source, $target, $relation, 10);

    echo "   ✅ Created dependency edge:\n";
    echo "      • Source: {$edge->getSource()->getShortName()}\n";
    echo "      • Target: {$edge->getTarget()->getShortName()}\n";
    echo "      • Relation: {$edge->getRelation()->value}\n";
    echo "      • Weight: {$edge->getWeight()}\n";
    echo "      • Is strong: " . ($edge->isStrong() ? 'Yes' : 'No') . "\n";
    echo "      • Description: {$edge->getRelation()->getDescription()}\n\n";

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

echo "3. Testing DependencyGraph operations:\n";

try {
    $graph = DependencyGraph::empty();

    // Create some nodes
    $routePathNode = DependencyNode::create(
        ClassName::create('App\\Framework\\Router\\ValueObjects\\RoutePath'),
        DependencyType::VALUE_OBJECT
    );

    $routeGroupNode = DependencyNode::create(
        ClassName::create('App\\Framework\\Router\\ValueObjects\\RouteGroup'),
        DependencyType::VALUE_OBJECT
    );

    $placeholderNode = DependencyNode::create(
        ClassName::create('App\\Framework\\Router\\ValueObjects\\Placeholder'),
        DependencyType::VALUE_OBJECT
    );

    // Add nodes to graph
    $graph = $graph->addNode($routePathNode);
    $graph = $graph->addNode($routeGroupNode);
    $graph = $graph->addNode($placeholderNode);

    echo "   ✅ Added nodes to graph:\n";
    echo "      • Node count: {$graph->getNodeCount()}\n";
    echo "      • Edge count: {$graph->getEdgeCount()}\n\n";

    // Create dependencies
    $edge1 = DependencyEdge::create(
        ClassName::create('App\\Framework\\Router\\ValueObjects\\RouteGroup'),
        ClassName::create('App\\Framework\\Router\\ValueObjects\\RoutePath'),
        DependencyRelation::CONSTRUCTOR_INJECTION,
        10
    );

    $edge2 = DependencyEdge::create(
        ClassName::create('App\\Framework\\Router\\ValueObjects\\RoutePath'),
        ClassName::create('App\\Framework\\Router\\ValueObjects\\Placeholder'),
        DependencyRelation::METHOD_PARAMETER,
        5
    );

    // Add edges
    $graph = $graph->addEdge($edge1);
    $graph = $graph->addEdge($edge2);

    echo "   ✅ Added edges to graph:\n";
    echo "      • Node count: {$graph->getNodeCount()}\n";
    echo "      • Edge count: {$graph->getEdgeCount()}\n\n";

    // Test graph statistics
    $statistics = $graph->getStatistics();
    echo "   📊 Graph statistics:\n";
    echo "      • Total nodes: {$statistics['node_count']}\n";
    echo "      • Total edges: {$statistics['edge_count']}\n";
    echo "      • Circular dependencies: {$statistics['circular_dependencies']}\n";
    echo "      • Leaf nodes: {$statistics['leaf_nodes']}\n";
    echo "      • Root nodes: {$statistics['root_nodes']}\n";
    echo "      • Average complexity: {$statistics['average_complexity']}\n";
    echo "      • Total complexity: {$statistics['total_complexity']}\n\n";

    echo "   📈 Type distribution:\n";
    foreach ($statistics['type_distribution'] as $type => $count) {
        echo "      • {$type}: {$count}\n";
    }
    echo "\n";

    // Test specific node retrieval
    $retrievedNode = $graph->getNode(ClassName::create('App\\Framework\\Router\\ValueObjects\\RouteGroup'));
    if ($retrievedNode !== null) {
        echo "   🔍 Retrieved RouteGroup node:\n";
        echo "      • Dependencies: {$retrievedNode->getDependencyCount()}\n";
        echo "      • Dependents: {$retrievedNode->getDependentCount()}\n";
        echo "      • Complexity: {$retrievedNode->getComplexityScore()}\n\n";
    }

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

echo "4. Testing dependency type detection:\n";

try {
    $testCases = [
        'App\\Framework\\DI\\DefaultContainer' => ['service', false, false, false, false],
        'App\\Application\\Controllers\\UserController' => ['controller', false, false, false, false],
        'App\\Domain\\User\\UserRepository' => ['repository', false, false, false, false],
        'App\\Framework\\Core\\ValueObjects\\Email' => ['value_object', false, false, false, false],
        'App\\Framework\\Http\\Middleware\\AuthMiddleware' => ['middleware', false, false, false, false],
        'App\\Framework\\Events\\UserCreatedHandler' => ['event_handler', false, false, false, false],
        'App\\Framework\\Exceptions\\ValidationException' => ['exception', false, false, false, false],
        'SomeInterface' => ['interface', true, false, false, false],
        'SomeAbstractClass' => ['abstract_class', false, true, false, false],
        'SomeTrait' => ['trait', false, false, true, false],
        'SomeEnum' => ['enum', false, false, false, true],
    ];

    echo "   🧪 Testing type detection:\n";
    foreach ($testCases as $className => [$expectedType, $isInterface, $isAbstract, $isTrait, $isEnum]) {
        $detectedType = DependencyType::fromClassName($className, $isInterface, $isAbstract, $isTrait, $isEnum);
        $match = $detectedType->value === $expectedType ? '✅' : '❌';
        echo "      {$match} {$className}: {$detectedType->value} (expected: {$expectedType})\n";
    }
    echo "\n";

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

echo "5. Testing circular dependency detection:\n";

try {
    $graph = DependencyGraph::empty();

    // Create a circular dependency: A -> B -> C -> A
    $nodeA = DependencyNode::create(ClassName::create('ClassA'), DependencyType::SERVICE);
    $nodeB = DependencyNode::create(ClassName::create('ClassB'), DependencyType::SERVICE);
    $nodeC = DependencyNode::create(ClassName::create('ClassC'), DependencyType::SERVICE);

    $graph = $graph->addNode($nodeA);
    $graph = $graph->addNode($nodeB);
    $graph = $graph->addNode($nodeC);

    $edgeAB = DependencyEdge::create(
        ClassName::create('ClassA'),
        ClassName::create('ClassB'),
        DependencyRelation::CONSTRUCTOR_INJECTION
    );

    $edgeBC = DependencyEdge::create(
        ClassName::create('ClassB'),
        ClassName::create('ClassC'),
        DependencyRelation::CONSTRUCTOR_INJECTION
    );

    $edgeCA = DependencyEdge::create(
        ClassName::create('ClassC'),
        ClassName::create('ClassA'),
        DependencyRelation::CONSTRUCTOR_INJECTION
    );

    $graph = $graph->addEdge($edgeAB);
    $graph = $graph->addEdge($edgeBC);
    $graph = $graph->addEdge($edgeCA);

    $circularDependencies = $graph->findCircularDependencies();

    echo "   🔄 Circular dependency test:\n";
    echo "      • Cycles found: " . count($circularDependencies) . "\n";
    if (! empty($circularDependencies)) {
        foreach ($circularDependencies as $cycle) {
            echo "      • Cycle: " . implode(' -> ', $cycle) . "\n";
        }
    }
    echo "\n";

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

echo "=== Dependency Graph Value Objects Test Completed ===\n";
