<?php

declare(strict_types=1);

namespace NoahVet\Reef\Test\A_Unit\Domain\Tool;

use NoahVet\Reef\Domain\Tool\StringTool;
use PHPUnit\Framework\TestCase;

final class StringToolTest extends TestCase
{
    private StringTool $subject;

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

    public function testFromBurgerCaseToSnakeCase(): void
    {
        self::assertSame(
            'once_upon_a_time',
            $this->subject::fromBurgerCaseToSnakeCase('once-upon-a-time'),
        );
    }

    public function testFromBurgerCaseToSnakeCaseAlreadyInSnakeCase(): void
    {
        self::assertSame(
            'once_upon_a_time',
            $this->subject::fromBurgerCaseToSnakeCase('once_upon_a_time'),
        );
    }

    public function testFromSnakeCaseToBurgerCase(): void
    {
        self::assertSame(
            'once-upon-a-time',
            $this->subject::fromSnakeCaseToBurgerCase('once_upon_a_time'),
        );
    }

    public function testFromSnakeCaseToBurgerCaseAlreadyInBurgerCase(): void
    {
        self::assertSame(
            'once-upon-a-time',
            $this->subject::fromSnakeCaseToBurgerCase('once-upon-a-time'),
        );
    }

    public function testFromSpacedToBurgerCase(): void
    {
        self::assertSame(
            'once-upon-a-time',
            $this->subject::fromSpacedToBurgerCase('Once upon a time'),
        );
    }

    public function testFromSpacedToBurgerCaseAlreadyInSnakeCase(): void
    {
        self::assertSame(
            'once-upon-a-time',
            $this->subject::fromSpacedToBurgerCase('once-upon-a-time'),
        );
    }

    public function testFromSpacedToUpperBurgerCase(): void
    {
        self::assertSame(
            'ONCE-UPON-A-TIME',
            $this->subject::fromSpacedToUpperBurgerCase('Once upon a time'),
        );
    }

    public function testFromSpacedToUpperBurgerCaseAlreadyInSnakeCase(): void
    {
        self::assertSame(
            'ONCE-UPON-A-TIME',
            $this->subject::fromSpacedToUpperBurgerCase('ONCE-UPON-A-TIME'),
        );
    }

    public function testFromPascalCaseToCamelCase(): void
    {
        self::assertSame(
            'inPascalCase',
            $this->subject::fromPascalCaseToCamelCase('InPascalCase'),
        );
    }

    public function testFromPascalCaseToCamelCaseAlreadyInCamelCase(): void
    {
        self::assertSame(
            'alreadyInCamelCase',
            $this->subject::fromPascalCaseToCamelCase('alreadyInCamelCase'),
        );
    }

    public function testFromSpacedToPascalCase(): void
    {
        self::assertSame(
            'Once Upon A Time',
            $this->subject::fromSpacedToPascalCase('once upon a time'),
        );
    }

    public function testFromSpacedToPascalCaseAlreadyInPascalCase(): void
    {
        self::assertSame(
            'Once Upon A Time',
            $this->subject::fromSpacedToPascalCase('Once Upon A Time'),
        );
    }

    public function testFromSpacedToSnakeUpperCase(): void
    {
        self::assertSame(
            'ONCE_UPON_A_TIME',
            $this->subject::fromSpacedToSnakeUpperCase(' Once Upon A Time '),
        );
    }

    public function testFromSpacedToSnakeUpperCaseAlreadyInSnakeUpperCase(): void
    {
        self::assertSame(
            'ONCE_UPON_A_TIME',
            $this->subject::fromSpacedToSnakeUpperCase(' ONCE_UPON_A_TIME '),
        );
    }

    public function testToLowerCaseWithoutAccent(): void
    {
        self::assertSame(
            'aaaaaceeeeiiiinooooouuuuyaaaaaceeeeiiiinooooouuuuy',
            $this->subject::toLowerCaseWithoutAccent(' àáâãäçèéêëìíîïñòóôõöùúûüýÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ '),
        );
    }

    public function testToUpperCaseWithoutAccent(): void
    {
        self::assertSame(
            'AAAAACEEEEIIIINOOOOOUUUUYAAAAACEEEEIIIINOOOOOUUUUY',
            $this->subject::toUpperCaseWithoutAccent(' àáâãäçèéêëìíîïñòóôõöùúûüýÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ '),
        );
    }

    public function testRemoveAccent(): void
    {
        self::assertSame(
            'aaaaaceeeeiiiinooooouuuuyAAAAACEEEEIIIINOOOOOUUUUY',
            $this->subject::removeAccent(' àáâãäçèéêëìíîïñòóôõöùúûüýÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ '),
        );
    }

    public function testRemoveWhitespace(): void
    {
        self::assertSame(
            '',
            $this->subject::removeWhitespace(' '),
        );

        self::assertSame(
            '',
            $this->subject::removeWhitespace('  '),
        );

        self::assertSame(
            'aéz',
            $this->subject::removeWhitespace(' aéz '),
        );

        self::assertSame(
            'Aéz&-!)=',
            $this->subject::removeWhitespace(' A é z & - ! ) = '),
        );
    }

    public function testToName(): void
    {
        $names = [
            'aurelien' => 'Aurelien',
            ' Jean-Paul ' => 'Jean-Paul',
            'JeAN MaRie' => 'Jean Marie',
            'DE FUNES' => 'De Funes',
            'D\'Amico' => 'D\'Amico',
            ' ' => '',
            '' => '',
            '\'' => '\'',
        ];
        foreach ($names as $name => $expectedName) {
            self::assertSame(
                $expectedName,
                $this->subject::toName($name),
            );
        }
    }

    public function testToPascalCaseWithoutAccent(): void
    {
        self::assertSame(
            'OnceUponATime',
            $this->subject::toPascalCase(' onceUponATime '),
        );
    }

    public function testToPascalCaseWithAccent(): void
    {
        self::assertSame(
            'ÀBáâCãDä',
            $this->subject::toPascalCase(' àBáâCãDä '),
        );
    }

    public function testFromCamelCaseToBurgerCase(): void
    {
        self::assertSame(
            'a-A-báâ-cã-dä',
            $this->subject::fromCamelCaseToBurgerCase(' aABáâCãDä '),
        );
    }
}
