<?php

declare(strict_types=1);

namespace App\Framework\Discovery\ValueObjects;

enum DependencyRelation: string
{
    case CONSTRUCTOR_INJECTION = 'constructor_injection';
    case METHOD_PARAMETER = 'method_parameter';
    case PROPERTY_TYPE = 'property_type';
    case RETURN_TYPE = 'return_type';
    case EXTENDS = 'extends';
    case IMPLEMENTS = 'implements';
    case USES_TRAIT = 'uses_trait';
    case STATIC_CALL = 'static_call';
    case INSTANTIATION = 'instantiation';
    case TYPE_HINT = 'type_hint';

    /**
     * Get the strength of this dependency relationship
     */
    public function getStrength(): int
    {
        return match ($this) {
            self::CONSTRUCTOR_INJECTION => 10,
            self::EXTENDS => 9,
            self::IMPLEMENTS => 8,
            self::USES_TRAIT => 7,
            self::PROPERTY_TYPE => 6,
            self::METHOD_PARAMETER => 5,
            self::RETURN_TYPE => 4,
            self::INSTANTIATION => 3,
            self::STATIC_CALL => 2,
            self::TYPE_HINT => 1,
        };
    }

    /**
     * Check if this is a compile-time dependency
     */
    public function isCompileTime(): bool
    {
        return in_array($this, [
            self::EXTENDS,
            self::IMPLEMENTS,
            self::USES_TRAIT,
            self::CONSTRUCTOR_INJECTION,
            self::PROPERTY_TYPE,
        ]);
    }

    /**
     * Check if this is a runtime dependency
     */
    public function isRuntime(): bool
    {
        return in_array($this, [
            self::METHOD_PARAMETER,
            self::INSTANTIATION,
            self::STATIC_CALL,
        ]);
    }

    /**
     * Check if this creates a strong coupling
     */
    public function isStrongCoupling(): bool
    {
        return in_array($this, [
            self::CONSTRUCTOR_INJECTION,
            self::EXTENDS,
            self::IMPLEMENTS,
        ]);
    }

    /**
     * Check if this creates a weak coupling
     */
    public function isWeakCoupling(): bool
    {
        return in_array($this, [
            self::METHOD_PARAMETER,
            self::RETURN_TYPE,
            self::TYPE_HINT,
        ]);
    }

    /**
     * Get the inverted relation (for creating bidirectional edges)
     */
    public function invert(): self
    {
        return match ($this) {
            self::CONSTRUCTOR_INJECTION => self::CONSTRUCTOR_INJECTION, // Dependency -> Dependent
            self::METHOD_PARAMETER => self::METHOD_PARAMETER,
            self::PROPERTY_TYPE => self::PROPERTY_TYPE,
            self::RETURN_TYPE => self::RETURN_TYPE,
            self::EXTENDS => self::EXTENDS, // Child -> Parent becomes Parent -> Child
            self::IMPLEMENTS => self::IMPLEMENTS, // Implementation -> Interface becomes Interface -> Implementation
            self::USES_TRAIT => self::USES_TRAIT, // User -> Trait becomes Trait -> User
            self::STATIC_CALL => self::STATIC_CALL,
            self::INSTANTIATION => self::INSTANTIATION,
            self::TYPE_HINT => self::TYPE_HINT,
        };
    }

    /**
     * Get the description of this relationship
     */
    public function getDescription(): string
    {
        return match ($this) {
            self::CONSTRUCTOR_INJECTION => 'Constructor dependency injection',
            self::METHOD_PARAMETER => 'Method parameter type hint',
            self::PROPERTY_TYPE => 'Property type declaration',
            self::RETURN_TYPE => 'Method return type',
            self::EXTENDS => 'Class inheritance',
            self::IMPLEMENTS => 'Interface implementation',
            self::USES_TRAIT => 'Trait usage',
            self::STATIC_CALL => 'Static method call',
            self::INSTANTIATION => 'Direct instantiation',
            self::TYPE_HINT => 'Type hint usage',
        };
    }

    /**
     * Get the impact on container resolution
     */
    public function getContainerImpact(): string
    {
        return match ($this) {
            self::CONSTRUCTOR_INJECTION => 'High - Required for instantiation',
            self::METHOD_PARAMETER => 'Medium - Required for method calls',
            self::PROPERTY_TYPE => 'Low - Static typing only',
            self::RETURN_TYPE => 'Low - Return type validation',
            self::EXTENDS => 'High - Parent class must be resolved',
            self::IMPLEMENTS => 'Medium - Interface binding affects resolution',
            self::USES_TRAIT => 'Low - Trait methods are copied',
            self::STATIC_CALL => 'Low - No instance required',
            self::INSTANTIATION => 'Medium - Direct instantiation bypasses container',
            self::TYPE_HINT => 'Low - Documentation only',
        };
    }

    /**
     * Convert to string
     */
    public function toString(): string
    {
        return $this->value;
    }
}
