<?php

namespace Velis\Test;

use PHPUnit\Framework\TestCase;
use Velis\AllowedIdsFilter;

class AllowedIdsFilterTest extends TestCase
{
    private AllowedIdsFilter $allowedIdsFilter;

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

    /**
     * Test that the function returns an empty array when all inputs are empty.
     */
    public function testEmptyInput()
    {
        $userAllowedIds = [];
        $currentIds = [];
        $inputIds = [];
        $expected = [];

        $this->assertEquals(
            $expected,
            $this->allowedIdsFilter->getUpdatedList($userAllowedIds, $currentIds, $inputIds)
        );
    }

    /**
     * Test that only allowed IDs are added to the list when the current list is empty.
     */
    public function testOnlyAllowedIdsAdded()
    {
        $userAllowedIds = [1, 2, 3];
        $currentIds = [];
        $inputIds = [1, 2];
        $expected = [1, 2];

        $this->assertEquals(
            $expected,
            $this->allowedIdsFilter->getUpdatedList($userAllowedIds, $currentIds, $inputIds)
        );
    }

    /**
     * Test that unallowed IDs are removed from the current list.
     */
    public function testRemoveUnallowedIds()
    {
        $userAllowedIds = [1, 2, 3];
        $currentIds = [1, 2, 4];
        $inputIds = [1, 2];
        $expected = [1, 2, 4];

        $this->assertEquals(
            $expected,
            $this->allowedIdsFilter->getUpdatedList($userAllowedIds, $currentIds, $inputIds)
        );
    }

    /**
     * Test that allowed IDs are added and unallowed IDs are removed.
     */
    public function testAddAndRemoveIds()
    {
        $userAllowedIds = [1, 2, 3, 4, 5];
        $currentIds = [1, 3, 5];
        $inputIds = [2, 4];
        $expected = [2, 4];

        $this->assertEquals(
            $expected,
            $this->allowedIdsFilter->getUpdatedList($userAllowedIds, $currentIds, $inputIds)
        );
    }

    /**
     * Test a mix of adding and removing IDs, ensuring only allowed IDs are present.
     * Adding and removing only these IDs that user is allowed to.
     */
    public function testMixedOperations()
    {
        $userAllowedIds = [1, 2, 3, 4];
        $currentIds = [1, 2, 3, 5];
        $inputIds = [1, 2, 4];
        $expected = [1, 2, 4, 5];

        $this->assertEquals(
            $expected,
            $this->allowedIdsFilter->getUpdatedList($userAllowedIds, $currentIds, $inputIds)
        );
    }

    /**
     * Test that input IDs that are not allowed are not added to the current list.
     */
    public function testInputIdsNotAllowed()
    {
        $userAllowedIds = [1, 2, 3];
        $currentIds = [1, 2];
        $inputIds = [4, 5];
        $expected = [];

        $this->assertEquals(
            $expected,
            $this->allowedIdsFilter->getUpdatedList($userAllowedIds, $currentIds, $inputIds)
        );
    }

    /**
     * Test that only allowed input IDs are added to the current list.
     */
    public function testInputIdsPartiallyAllowed()
    {
        $userAllowedIds = [1, 2, 3];
        $currentIds = [1, 2];
        $inputIds = [1, 2, 3, 4];
        $expected = [1, 2, 3];

        $this->assertEquals(
            $expected,
            $this->allowedIdsFilter->getUpdatedList($userAllowedIds, $currentIds, $inputIds)
        );
    }

    /**
     * Test that duplicates in the input IDs are handled correctly.
     */
    public function testDuplicatesInInput()
    {
        $userAllowedIds = [1, 2, 3];
        $currentIds = [1, 2];
        $inputIds = [1, 2, 2, 3];
        $expected = [1, 2, 3];

        $this->assertEquals(
            $expected,
            $this->allowedIdsFilter->getUpdatedList($userAllowedIds, $currentIds, $inputIds)
        );
    }
}
