<?php

declare(strict_types=1);

namespace App\Framework\GraphQL\ValueObjects;

use App\Framework\Exception\ErrorCode;
use App\Framework\Exception\FrameworkException;

/**
 * Represents a valid GraphQL type name
 *
 * Type names must:
 * - Start with a letter or underscore
 * - Contain only letters, numbers, and underscores
 * - Not start with double underscores (reserved for introspection)
 */
final readonly class GraphQLTypeName
{
    private function __construct(
        public string $value
    ) {
    }

    public static function fromString(string $name): self
    {
        $trimmed = trim($name);

        if (empty($trimmed)) {
            throw FrameworkException::create(
                ErrorCode::VAL_BUSINESS_RULE_VIOLATION,
                'GraphQL type name cannot be empty'
            );
        }

        // Check for reserved double underscore prefix
        if (str_starts_with($trimmed, '__')) {
            throw FrameworkException::create(
                ErrorCode::VAL_BUSINESS_RULE_VIOLATION,
                'GraphQL type names starting with "__" are reserved for introspection'
            )->withData(['name' => $trimmed]);
        }

        // Validate pattern: must start with letter or underscore, followed by alphanumeric or underscore
        if (! preg_match('/^[_a-zA-Z][_a-zA-Z0-9]*$/', $trimmed)) {
            throw FrameworkException::create(
                ErrorCode::VAL_BUSINESS_RULE_VIOLATION,
                'Invalid GraphQL type name. Must start with letter or underscore, contain only alphanumeric characters and underscores'
            )->withData(['name' => $trimmed]);
        }

        return new self($trimmed);
    }

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

    public function equals(self $other): bool
    {
        return $this->value === $other->value;
    }

    public function __toString(): string
    {
        return $this->value;
    }
}
