<?php

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

use NoahVet\Reef\Domain\Tool\ArrayTool;
use NoahVet\Reef\Domain\Tool\ArrayToolInterface;
use PHPUnit\Framework\TestCase;

final class ArrayToolTest extends TestCase
{
    private ArrayToolInterface $subject;

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

    public function testRemoveDeepDuplicateValues(): void
    {
        $before = [
            0 => [
                'id' => 'eb0220aa-8731-4afe-9a62-e6c3fa13b7f2',
            ],
            1 => [
                'id' => 'eb0220aa-8731-4afe-9a62-e6c3fa13b7f2',
            ],
            2 => [
                'id' => 'eb0220aa-8731-4afe-9a62-e6c3fa13b7f2',
            ],
        ];
        $expected = [
            0 => [
                'id' => 'eb0220aa-8731-4afe-9a62-e6c3fa13b7f2',
            ],
        ];

        self::assertSame(
            $expected,
            $this->subject::removeDeepDuplicateValues($before, 'id'),
        );
    }

    public function testRemoveDuplicateValues(): void
    {
        $before = [
            0 => [
                'id' => 'eb0220aa-8731-4afe-9a62-e6c3fa13b7f2',
            ],
            1 => [
                'id' => 'eb0220aa-8731-4afe-9a62-e6c3fa13b7f2',
            ],
            2 => [
                'id' => 'eb0220aa-8731-4afe-9a62-e6c3fa13b7f2',
            ],
        ];
        $expected = [
            0 => [
                'id' => 'eb0220aa-8731-4afe-9a62-e6c3fa13b7f2',
            ],
        ];
        /** @var \Traversable $result */
        $result = $this->subject::removeDuplicates($before, 'id');

        self::assertSame(
            $expected,
            \iterator_to_array($result),
        );
    }

    public function testApplyTrimRecursiveWhenDataIsArray(): void
    {
        $data = [
            0 => [
                'id' => ' azerty123456789-_+ ',
            ],
            1 => [
                'id' => 'azerty123456789-_+  ',
            ],
            2 => [
                'id' => 'azerty123456789-_+  ',
            ],
            3 => [
                'id' => '            ',
            ],
            4 => [
                'id' => '    o        ',
            ],
            5 => null,
            6 => true,
            7 => false,
        ];

        $expected = [
            0 => [
                'id' => 'azerty123456789-_+',
            ],
            1 => [
                'id' => 'azerty123456789-_+',
            ],
            2 => [
                'id' => 'azerty123456789-_+',
            ],
            3 => [
                'id' => '',
            ],
            4 => [
                'id' => 'o',
            ],
            5 => null,
            6 => true,
            7 => false,
        ];
        $this->subject::applyTrimRecursive($data);

        self::assertSame(
            $expected,
            $data,
        );
    }

    public function testApplyTrimRecursiveWhenDataIsString(): void
    {
        $data = "  azerty01234567989-é'(è'(&'   ";
        $expected = "azerty01234567989-é'(è'(&'";

        $this->subject::applyTrimRecursive($data);

        self::assertSame(
            $expected,
            $data,
        );
    }

    public function testApplyTrimRecursiveWhenDataIsNull(): void
    {
        $data = null;
        $expected = null;

        $this->subject::applyTrimRecursive($data);

        self::assertSame(
            $expected,
            $data,
        );
    }

    public function testSortMultiDimensionalByKeyWithEmptyArray(): void
    {
        $array = [];
        $expected = [];

        $result = ArrayTool::sortMultiDimensionalByKey($array);

        $this->assertSame($expected, $result);
    }

    public function testSortMultiDimensionalByKeyWithSimpleArray(): void
    {
        $array = [
            'b' => 2,
            'a' => 1,
            'c' => 3,
        ];
        $expected = [
            'a' => 1,
            'b' => 2,
            'c' => 3,
        ];

        $result = ArrayTool::sortMultiDimensionalByKey($array);

        $this->assertSame($expected, $result);
    }

    public function testSortMultiDimensionalByKeyWithNestedArray(): void
    {
        $array = [
            'b' => ['d' => 4, 'c' => 3],
            'a' => ['f' => 6, 'e' => 5],
        ];
        $expected = [
            'a' => ['e' => 5, 'f' => 6],
            'b' => ['c' => 3, 'd' => 4],
        ];

        $result = ArrayTool::sortMultiDimensionalByKey($array);

        $this->assertSame($expected, $result);
    }

    public function testSortMultiDimensionalByKeyWithDeepNestedArray(): void
    {
        $array = [
            'z' => [
                'b' => ['d' => 4, 'c' => 3],
                'a' => ['f' => 6, 'e' => 5],
            ],
            'x' => [
                'y' => 10,
            ],
        ];
        $expected = [
            'x' => [
                'y' => 10,
            ],
            'z' => [
                'a' => ['e' => 5, 'f' => 6],
                'b' => ['c' => 3, 'd' => 4],
            ],
        ];

        $result = ArrayTool::sortMultiDimensionalByKey($array);

        $this->assertSame($expected, $result);
    }

    public function testSortMultiDimensionalByKeyWithNonArrayValues(): void
    {
        $array = [
            'b' => 'string',
            'a' => 123,
            'c' => ['d' => 4],
        ];
        $expected = [
            'a' => 123,
            'b' => 'string',
            'c' => ['d' => 4],
        ];

        $result = ArrayTool::sortMultiDimensionalByKey($array);

        $this->assertSame($expected, $result);
    }
}
