<?php

namespace App\Tests\Unit\Service\Utils;

use App\Service\Utils\ArrayUtils;
use PHPUnit\Framework\TestCase;

class ArrayUtilsTest extends TestCase
{
    public function testAll(): void {

        $isEven = function ($num) { return $num % 2 === 0; };

        $this->assertFalse(
            ArrayUtils::all([1, 2, 3], $isEven)
        );

        $this->assertTrue(
            ArrayUtils::all([2, 4, 6], $isEven)
        );
    }

    public function testAny(): void {

        $isEven = function ($num) { return $num % 2 === 0; };

        $this->assertFalse(
            ArrayUtils::any([1, 3, 5], $isEven)
        );

        $this->assertTrue(
            ArrayUtils::any([1, 2, 3], $isEven)
        );
    }



    /**
     * @øee ArrayUtils::getChanges()
     */
    public function testGetChanges(): void
    {
        $arrayUtils = new ArrayUtils();

        // Non-recursive (default)
        $this->assertEquals(
            ['b' => -2, 'c' => ['d' => 4, 'e' => ['f' => -5]], 'g' => 7],
            $arrayUtils->getChanges(
                ['a' => 1, 'b' => 2, 'c' => ['d' => 4, 'e' => ['f' => 5]]],
                ['a' => 1, 'b' => -2, 'c' => ['d' => 4, 'e' => ['f' => -5]], 'g' => 7],
            )
        );

        // Recursive
        $this->assertEquals(
            ['b' => -2, 'c' => ['e' => ['f' => -5]], 'g' => 7],
            $arrayUtils->getChanges(
                ['a' => 1, 'b' => 2, 'c' => ['d' => 4, 'e' => ['f' => 5]]],
                ['a' => 1, 'b' => -2, 'c' => ['d' => 4, 'e' => ['f' => -5]], 'g' => 7],
                true
            )
        );

        // Recursive with unchanged sub array
        $this->assertEquals(
            ['b' => -2],
            $arrayUtils->getChanges(
                ['a' => 1, 'b' => 2, 'c' => ['d' => 4, 'e' => ['f' => 5]]],
                ['a' => 1, 'b' => -2, 'c' => ['d' => 4, 'e' => ['f' => 5]]],
                true
            )
        );

        // No changes
        $this->assertEquals(
            [],
            $arrayUtils->getChanges(
                ['a' => 1, 'b' => 2, 'c' => ['d' => 4, 'e' => ['f' => 5]]],
                ['a' => 1, 'b' => 2, 'c' => ['d' => 4, 'e' => ['f' => 5]]],
            )
        );

        // Empty arrays
        $this->assertEquals(
            [],
            $arrayUtils->getChanges(
                [],
                [],
            )
        );

        // First array is empty
        $this->assertEquals(
            ['a' => 1],
            $arrayUtils->getChanges(
                [],
                ['a' => 1],
            )
        );

        // With callback
        $this->assertEquals(
            ['a' => 2],
            $arrayUtils->getChanges(
                ['a' => 1, 'b' => ''],
                ['a' => 2, 'b' => null],
                false,
                static function ($v1, $v2) { return ($v1 ?? '') === ($v2 ?? ''); }
            )
        );
    }

    public function testGetAndCast(): void {
        $this->assertEquals(
            123,
            ArrayUtils::getAndCast(["a" => "123"], 'a', 'int')
        );
    }

    public function testGetAndCastMissingKey(): void {
        $this->assertEquals(
            null,
            ArrayUtils::getAndCast(["a" => "123"], 'b', 'int')
        );
    }

}
