<?php

declare(strict_types=1);

namespace App\Framework\Queue\ValueObjects;

/**
 * Value Object für Lock Keys im Distributed Locking System
 */
final readonly class LockKey
{
    private function __construct(
        private string $value
    ) {
        if (empty($value)) {
            throw new \InvalidArgumentException('Lock key cannot be empty');
        }

        if (strlen($value) > 255) {
            throw new \InvalidArgumentException('Lock key cannot exceed 255 characters');
        }

        // Nur alphanumerische Zeichen, Bindestriche, Unterstriche und Punkte erlaubt
        if (! preg_match('/^[a-zA-Z0-9\-_.]+$/', $value)) {
            throw new \InvalidArgumentException('Lock key contains invalid characters');
        }
    }

    /**
     * Lock Key aus String erstellen
     */
    public static function fromString(string $key): self
    {
        return new self($key);
    }

    /**
     * Lock Key für Job erstellen
     */
    public static function forJob(JobId $jobId): self
    {
        return new self("job.{$jobId->toString()}");
    }

    /**
     * Lock Key für Queue erstellen
     */
    public static function forQueue(QueueName $queueName): self
    {
        return new self("queue.{$queueName->toString()}");
    }

    /**
     * Lock Key für Worker erstellen
     */
    public static function forWorker(WorkerId $workerId): self
    {
        return new self("worker.{$workerId->toString()}");
    }

    /**
     * Lock Key für Resource erstellen
     */
    public static function forResource(string $resourceType, string $resourceId): self
    {
        return new self("{$resourceType}.{$resourceId}");
    }

    /**
     * Lock Key für Batch-Operation erstellen
     */
    public static function forBatch(string $batchId): self
    {
        return new self("batch.{$batchId}");
    }

    /**
     * String Repräsentation
     */
    public function toString(): string
    {
        return $this->value;
    }

    /**
     * Prüfe ob zwei LockKeys gleich sind
     */
    public function equals(self $other): bool
    {
        return $this->value === $other->value;
    }

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

    /**
     * JSON Serialization
     */
    public function jsonSerialize(): string
    {
        return $this->value;
    }

    /**
     * Lock Key mit Prefix erweitern
     */
    public function withPrefix(string $prefix): self
    {
        return new self("{$prefix}.{$this->value}");
    }

    /**
     * Lock Key mit Suffix erweitern
     */
    public function withSuffix(string $suffix): self
    {
        return new self("{$this->value}.{$suffix}");
    }

    /**
     * Prüfe ob Lock Key ein bestimmtes Pattern hat
     */
    public function matches(string $pattern): bool
    {
        return fnmatch($pattern, $this->value);
    }
}
