<?php

declare(strict_types=1);

namespace App\Framework\DI\Exceptions;

use App\Framework\Exception\ExceptionContext;

/**
 * Exception thrown when DefaultImplementation attribute validation fails
 */
final class DefaultImplementationException extends ContainerException
{
    /**
     * Thrown when a class with DefaultImplementation attribute does not implement the specified interface
     *
     * @param class-string $className
     * @param class-string $interface
     */
    public static function doesNotImplementInterface(string $className, string $interface): self
    {
        $message = sprintf(
            'Class "%s" has #[DefaultImplementation] for interface "%s" but does not implement that interface',
            $className,
            $interface
        );

        $context = ExceptionContext::forOperation('default_implementation_validation', 'DI Container')
            ->withData([
                'className' => $className,
                'interface' => $interface,
                'errorType' => 'does_not_implement_interface',
            ]);

        return new self($message, $context);
    }

    /**
     * Thrown when a class with DefaultImplementation attribute (without explicit interface) implements no interfaces
     *
     * @param class-string $className
     */
    public static function noInterfacesImplemented(string $className): self
    {
        $message = sprintf(
            'Class "%s" has #[DefaultImplementation] without explicit interface but implements no interfaces. ' .
            'Either specify an interface explicitly or ensure the class implements at least one interface.',
            $className
        );

        $context = ExceptionContext::forOperation('default_implementation_validation', 'DI Container')
            ->withData([
                'className' => $className,
                'errorType' => 'no_interfaces_implemented',
            ]);

        return new self($message, $context);
    }

    /**
     * Thrown when the specified interface does not exist
     *
     * @param class-string $className
     * @param string $interface
     */
    public static function interfaceDoesNotExist(string $className, string $interface): self
    {
        $message = sprintf(
            'Class "%s" has #[DefaultImplementation] for interface "%s" which does not exist',
            $className,
            $interface
        );

        $context = ExceptionContext::forOperation('default_implementation_validation', 'DI Container')
            ->withData([
                'className' => $className,
                'interface' => $interface,
                'errorType' => 'interface_does_not_exist',
            ]);

        return new self($message, $context);
    }
}
