<?php

namespace MintyPHP\Tests\Repository\Support;

use MintyPHP\Repository\Support\RepositoryArrayHelper;
use PHPUnit\Framework\TestCase;

class RepositoryArrayHelperTest extends TestCase
{
    // --- unwrap ---

    public function testUnwrapReturnsInnerArray(): void
    {
        $row = ['tenants' => ['id' => 1, 'description' => 'A']];
        $this->assertSame(['id' => 1, 'description' => 'A'], RepositoryArrayHelper::unwrap($row, 'tenants'));
    }

    public function testUnwrapReturnsNullForMissingKey(): void
    {
        $row = ['other' => ['id' => 1]];
        $this->assertNull(RepositoryArrayHelper::unwrap($row, 'tenants'));
    }

    public function testUnwrapReturnsNullForNullInput(): void
    {
        $this->assertNull(RepositoryArrayHelper::unwrap(null, 'tenants'));
    }

    public function testUnwrapReturnsNullForEmptyArray(): void
    {
        $this->assertNull(RepositoryArrayHelper::unwrap([], 'tenants'));
    }

    // --- unwrapList ---

    public function testUnwrapListExtractsRows(): void
    {
        $rows = [
            ['roles' => ['id' => 1, 'description' => 'Admin']],
            ['roles' => ['id' => 2, 'description' => 'User']],
        ];
        $result = RepositoryArrayHelper::unwrapList($rows, 'roles');
        $this->assertCount(2, $result);
        $this->assertSame(1, $result[0]['id']);
        $this->assertSame(2, $result[1]['id']);
    }

    public function testUnwrapListSkipsNonArrayEntries(): void
    {
        $rows = [
            ['roles' => ['id' => 1]],
            ['roles' => null],
            ['other' => ['id' => 3]],
        ];
        $result = RepositoryArrayHelper::unwrapList($rows, 'roles');
        $this->assertCount(1, $result);
        $this->assertSame(1, $result[0]['id']);
    }

    public function testUnwrapListReturnsEmptyForNonArray(): void
    {
        $this->assertSame([], RepositoryArrayHelper::unwrapList(null, 'roles'));
        $this->assertSame([], RepositoryArrayHelper::unwrapList(false, 'roles'));
    }

    public function testUnwrapListReturnsEmptyForEmptyArray(): void
    {
        $this->assertSame([], RepositoryArrayHelper::unwrapList([], 'roles'));
    }

    // --- extractIds ---

    public function testExtractIdsFromWrappedRows(): void
    {
        $rows = [
            ['tenants' => ['id' => 1]],
            ['tenants' => ['id' => 2]],
            ['tenants' => ['id' => 3]],
        ];
        $this->assertSame([1, 2, 3], RepositoryArrayHelper::extractIds($rows, 'tenants'));
    }

    public function testExtractIdsDeduplicates(): void
    {
        $rows = [
            ['tenants' => ['id' => 1]],
            ['tenants' => ['id' => 1]],
            ['tenants' => ['id' => 2]],
        ];
        $this->assertSame([1, 2], RepositoryArrayHelper::extractIds($rows, 'tenants'));
    }

    public function testExtractIdsFallsBackToRowItself(): void
    {
        $rows = [
            ['id' => 5],
            ['id' => 6],
        ];
        $this->assertSame([5, 6], RepositoryArrayHelper::extractIds($rows, 'missing_key'));
    }

    public function testExtractIdsWithCustomIdField(): void
    {
        $rows = [
            ['user_roles' => ['role_id' => 10]],
            ['user_roles' => ['role_id' => 20]],
        ];
        $this->assertSame([10, 20], RepositoryArrayHelper::extractIds($rows, 'user_roles', 'role_id'));
    }

    public function testExtractIdsSkipsMissingIdField(): void
    {
        $rows = [
            ['tenants' => ['id' => 1]],
            ['tenants' => ['name' => 'no id']],
        ];
        $this->assertSame([1], RepositoryArrayHelper::extractIds($rows, 'tenants'));
    }

    public function testExtractIdsReturnsEmptyForNonArray(): void
    {
        $this->assertSame([], RepositoryArrayHelper::extractIds(null, 'tenants'));
        $this->assertSame([], RepositoryArrayHelper::extractIds(false, 'tenants'));
    }

    public function testExtractIdsReturnsEmptyForEmptyArray(): void
    {
        $this->assertSame([], RepositoryArrayHelper::extractIds([], 'tenants'));
    }

    // --- sanitizePositiveIds ---

    public function testSanitizePositiveIdsFiltersAndDeduplicates(): void
    {
        $this->assertSame([1, 3, 5], RepositoryArrayHelper::sanitizePositiveIds([1, 3, 5, 1, 3]));
    }

    public function testSanitizePositiveIdsRemovesZeroAndNegative(): void
    {
        $this->assertSame([2, 4], RepositoryArrayHelper::sanitizePositiveIds([0, -1, 2, -3, 4]));
    }

    public function testSanitizePositiveIdsCastsToInt(): void
    {
        $this->assertSame([1, 2, 3], RepositoryArrayHelper::sanitizePositiveIds(['1', '2', '3']));
    }

    public function testSanitizePositiveIdsReturnsEmptyForEmpty(): void
    {
        $this->assertSame([], RepositoryArrayHelper::sanitizePositiveIds([]));
    }

    public function testSanitizePositiveIdsReturnsEmptyForAllInvalid(): void
    {
        $this->assertSame([], RepositoryArrayHelper::sanitizePositiveIds([0, -1, -2]));
    }

    public function testSanitizePositiveIdsReindexes(): void
    {
        $result = RepositoryArrayHelper::sanitizePositiveIds([0, 0, 5]);
        $this->assertSame([5], $result);
        $this->assertSame(0, array_key_first($result));
    }

    // --- flattenRow ---

    public function testFlattenRowMergesNestedTableArrays(): void
    {
        $row = [
            'api_audit_log' => ['id' => 1, 'request_id' => 'abc'],
            'users' => ['display_name' => 'Alice'],
            'tenants' => ['description' => 'Tenant A'],
        ];

        $this->assertSame(
            [
                'id' => 1,
                'request_id' => 'abc',
                'display_name' => 'Alice',
                'description' => 'Tenant A',
            ],
            RepositoryArrayHelper::flattenRow($row)
        );
    }

    public function testFlattenRowKeepsTopLevelScalarValues(): void
    {
        $row = [
            'status' => 'ok',
            'count' => 3,
        ];

        $this->assertSame(['status' => 'ok', 'count' => 3], RepositoryArrayHelper::flattenRow($row));
    }

    public function testFlattenRowReturnsEmptyForNonArray(): void
    {
        $this->assertSame([], RepositoryArrayHelper::flattenRow(null));
        $this->assertSame([], RepositoryArrayHelper::flattenRow(false));
        $this->assertSame([], RepositoryArrayHelper::flattenRow('text'));
    }
}
