<?php

namespace AutoAdmin\Bundle\Tests\Unit\Content\Duplicator\Service;

use AutoAdmin\Bundle\Content\Duplicator\Enum\StringDuplicateModeEnum;
use AutoAdmin\Bundle\Content\Duplicator\Service\StringDuplicator;
use PHPUnit\Framework\TestCase;

class StringDuplicatorTest extends TestCase
{
    private StringDuplicator $duplicator;

    protected function setUp(): void
    {
        $this->duplicator = new StringDuplicator();
    }

    public function testGetLabelMarker(): void
    {
        $this->assertSame(' (dup)', $this->duplicator->getLabelMarker());
    }

    public function testGetNoSepSlugMarker(): void
    {
        $this->assertSame('dup', $this->duplicator->getNoSepSlugMarker());
    }

    public function testGetKebabSlugMarker(): void
    {
        $this->assertSame('-dup', $this->duplicator->getKebabSlugMarker());
    }

    public function testGetSnakeSlugMarker(): void
    {
        $this->assertSame('_dup', $this->duplicator->getSnakeSlugMarker());
    }

    public function testDuplicateSlugKebabAddsMarker(): void
    {
        $result = $this->duplicator->duplicate('my-slug', StringDuplicateModeEnum::KEBAB);

        $this->assertMatchesRegularExpression('/^my-slug-dup-[a-zA-Z0-9]{3}$/', $result);
    }

    public function testDuplicateSlugKebabReplacesExistingMarker(): void
    {
        $alreadyDuplicated = 'my-slug-dup-abc';
        $result = $this->duplicator->duplicate($alreadyDuplicated, StringDuplicateModeEnum::KEBAB);

        $this->assertMatchesRegularExpression('/^my-slug-dup-[a-zA-Z0-9]{3}$/', $result);
        $this->assertNotSame($alreadyDuplicated, $result);
    }

    public function testDuplicateSlugSnakeAddsMarker(): void
    {
        $result = $this->duplicator->duplicate('my_slug', StringDuplicateModeEnum::SNAKE);

        $this->assertMatchesRegularExpression('/^my_slug_dup_[a-zA-Z0-9]{3}$/', $result);
    }

    public function testDuplicateSlugSnakeReplacesExistingMarker(): void
    {
        $alreadyDuplicated = 'my_slug_dup_abc';
        $result = $this->duplicator->duplicate($alreadyDuplicated, StringDuplicateModeEnum::SNAKE);

        $this->assertMatchesRegularExpression('/^my_slug_dup_[a-zA-Z0-9]{3}$/', $result);
        $this->assertNotSame($alreadyDuplicated, $result);
    }

    public function testDuplicateSlugLabelAddsMarker(): void
    {
        $result = $this->duplicator->duplicate('My Label', StringDuplicateModeEnum::LABEL);

        $this->assertMatchesRegularExpression('/^My Label \(dup\)$/', $result);
    }

    public function testDuplicateSlugLabelReplacesExistingMarker(): void
    {
        $alreadyDuplicated = 'My Label (dup)';
        $result = $this->duplicator->duplicate($alreadyDuplicated, StringDuplicateModeEnum::LABEL);

        $this->assertMatchesRegularExpression('/^My Label \(dup\)$/', $result);
    }

    public function testDuplicateSlugProducesUniqueSuffixes(): void
    {
        $results = [];
        for ($i = 0; $i < 10; $i++) {
            $results[] = $this->duplicator->duplicate('my-slug', StringDuplicateModeEnum::KEBAB);
        }

        $unique = array_unique($results);
        $this->assertGreaterThan(1, count($unique), 'Expected duplicate calls to produce different suffixes');
    }

    public function testDoubleDuplicateKebabDoesNotStackSuffixes(): void
    {
        $first = $this->duplicator->duplicate('my-slug', StringDuplicateModeEnum::KEBAB);
        $second = $this->duplicator->duplicate($first, StringDuplicateModeEnum::KEBAB);

        $this->assertMatchesRegularExpression('/^my-slug-dup-[a-z0-9]{3}$/', $second);
    }

    public function testDoubleDuplicateSnakeDoesNotStackSuffixes(): void
    {
        $first = $this->duplicator->duplicate('my_slug', StringDuplicateModeEnum::SNAKE);
        $second = $this->duplicator->duplicate($first, StringDuplicateModeEnum::SNAKE);

        $this->assertMatchesRegularExpression('/^my_slug_dup_[a-z0-9]{3}$/', $second);
    }

    public function testDoubleDuplicateLabelDoesNotStackSuffixes(): void
    {
        $first = $this->duplicator->duplicate('My Label', StringDuplicateModeEnum::LABEL);
        $second = $this->duplicator->duplicate($first, StringDuplicateModeEnum::LABEL);

        $this->assertMatchesRegularExpression('/^My Label \(dup\)$/', $second);
    }
}
