<?php

declare(strict_types=1);

namespace App\Framework\Discovery\Enhanced\ValueObjects;

/**
 * Dependency Edge representation
 *
 * Represents a dependency relationship between two components.
 */
final readonly class DependencyEdge
{
    public function __construct(
        public string $from,
        public string $to,
        public string $type,
        public float $strength = 1.0,
        public array $metadata = []
    ) {
    }

    /**
     * Get edge weight for graph algorithms
     */
    public function getWeight(): float
    {
        return $this->strength;
    }

    /**
     * Check if this is a strong dependency
     */
    public function isStrong(): bool
    {
        return $this->strength > 0.7;
    }

    /**
     * Check if this is a weak dependency
     */
    public function isWeak(): bool
    {
        return $this->strength < 0.3;
    }

    /**
     * Get dependency description
     */
    public function getDescription(): string
    {
        return match ($this->type) {
            'constructor' => 'Constructor dependency (injected)',
            'method' => 'Method parameter dependency',
            'attribute' => 'Attribute-based dependency',
            'inheritance' => 'Inheritance relationship',
            'composition' => 'Composition relationship',
            'aggregation' => 'Aggregation relationship',
            'usage' => 'Usage dependency',
            'event' => 'Event-based dependency',
            default => 'Unknown dependency type'
        };
    }

    /**
     * Get dependency criticality level
     */
    public function getCriticality(): string
    {
        return match ($this->type) {
            'constructor' => 'critical',
            'inheritance' => 'critical',
            'composition' => 'high',
            'method' => 'medium',
            'attribute' => 'medium',
            'aggregation' => 'low',
            'usage' => 'low',
            'event' => 'very_low',
            default => 'unknown'
        };
    }

    /**
     * Check if dependency can be easily removed
     */
    public function isRemovable(): bool
    {
        return match ($this->type) {
            'constructor', 'inheritance' => false,
            'composition' => false,
            'method' => $this->strength < 0.5,
            'attribute' => true,
            'aggregation' => true,
            'usage' => true,
            'event' => true,
            default => false
        };
    }

    /**
     * Get performance impact of this dependency
     */
    public function getPerformanceImpact(): string
    {
        $impact = match ($this->type) {
            'constructor' => 'startup',
            'method' => 'runtime',
            'attribute' => 'initialization',
            'inheritance' => 'startup',
            'composition' => 'startup',
            'aggregation' => 'runtime',
            'usage' => 'runtime',
            'event' => 'event_driven',
            default => 'unknown'
        };

        $severity = match (true) {
            $this->strength > 0.8 => 'high',
            $this->strength > 0.5 => 'medium',
            default => 'low'
        };

        return "{$severity}_{$impact}";
    }

    /**
     * Check if this dependency creates a potential circular reference
     */
    public function isCircularRisk(): bool
    {
        return in_array($this->type, ['composition', 'aggregation']) && $this->strength > 0.5;
    }

    /**
     * Get refactoring suggestions for this dependency
     */
    public function getRefactoringSuggestions(): array
    {
        $suggestions = [];

        if ($this->strength > 0.8 && $this->type === 'method') {
            $suggestions[] = [
                'type' => 'extract_interface',
                'description' => 'Consider extracting an interface to reduce coupling',
                'priority' => 'medium',
            ];
        }

        if ($this->type === 'usage' && $this->strength > 0.6) {
            $suggestions[] = [
                'type' => 'dependency_injection',
                'description' => 'Consider using dependency injection instead of direct usage',
                'priority' => 'high',
            ];
        }

        if ($this->isCircularRisk()) {
            $suggestions[] = [
                'type' => 'break_circular',
                'description' => 'This dependency may cause circular references. Consider using events or interfaces.',
                'priority' => 'critical',
            ];
        }

        if ($this->strength < 0.2) {
            $suggestions[] = [
                'type' => 'remove_dependency',
                'description' => 'This dependency is very weak and might be removable',
                'priority' => 'low',
            ];
        }

        return $suggestions;
    }

    /**
     * Convert to array representation
     */
    public function toArray(): array
    {
        return [
            'from' => $this->from,
            'to' => $this->to,
            'type' => $this->type,
            'strength' => round($this->strength, 3),
            'weight' => round($this->getWeight(), 3),
            'description' => $this->getDescription(),
            'criticality' => $this->getCriticality(),
            'is_strong' => $this->isStrong(),
            'is_weak' => $this->isWeak(),
            'is_removable' => $this->isRemovable(),
            'performance_impact' => $this->getPerformanceImpact(),
            'is_circular_risk' => $this->isCircularRisk(),
            'refactoring_suggestions' => $this->getRefactoringSuggestions(),
            'metadata' => $this->metadata,
        ];
    }

    /**
     * Create from array data
     */
    public static function fromArray(array $data): self
    {
        return new self(
            from: $data['from'],
            to: $data['to'],
            type: $data['type'],
            strength: $data['strength'] ?? 1.0,
            metadata: $data['metadata'] ?? []
        );
    }

    /**
     * Create a strong dependency edge
     */
    public static function strong(string $from, string $to, string $type): self
    {
        return new self($from, $to, $type, 0.9);
    }

    /**
     * Create a weak dependency edge
     */
    public static function weak(string $from, string $to, string $type): self
    {
        return new self($from, $to, $type, 0.2);
    }

    /**
     * Create a constructor dependency (always strong)
     */
    public static function constructor(string $from, string $to): self
    {
        return new self($from, $to, 'constructor', 0.95);
    }

    /**
     * Create a method dependency
     */
    public static function method(string $from, string $to, float $strength = 0.6): self
    {
        return new self($from, $to, 'method', $strength);
    }

    /**
     * Create an inheritance relationship (always critical)
     */
    public static function inheritance(string $from, string $to): self
    {
        return new self($from, $to, 'inheritance', 1.0);
    }

    /**
     * Create a composition relationship
     */
    public static function composition(string $from, string $to): self
    {
        return new self($from, $to, 'composition', 0.8);
    }

    /**
     * Create an event-based dependency (usually weak)
     */
    public static function event(string $from, string $to): self
    {
        return new self($from, $to, 'event', 0.3);
    }
}
