<?php

namespace Velis\Test;

use PHPUnit\Framework\TestCase;
use Psr\SimpleCache\InvalidArgumentException;
use User\User;
use Velis\Label;
use Velis\Model\DataObject\NoColumnsException;

/**
 * @author Jan Małysiak <jan.malysiak@velistech.com>
 */
class LabelTest extends TestCase
{
    /**
     * @param Label $label
     * @param User $user
     * @param bool $expectedResult
     * @return void
     *
     * @dataProvider provideTestDataForCheckAccessMethod
     */
    public function testCheckAccess(Label $label, User $user, bool $expectedResult): void
    {
        $actualResult = $label->checkAccess($user);

        self::assertEquals($expectedResult, $actualResult);
    }

    /**
     * @return array
     * @throws NoColumnsException
     */
    public function provideTestDataForCheckAccessMethod(): array
    {
        $userWithAllLabelAccess = $this->createMock(User::class);
        $userWithAllLabelAccess->method('hasPriv')
            ->willReturn(true);

        $userId = 1;
        $substitutedUserId = 2;
        $otherUserId = 3;

        $user = $this->createMock(User::class);
        $user->method('hasPriv')
            ->willReturn(false);
        $user->method('id')
            ->willReturn($userId);
        $user->method('getSubstitutedUserIds')
            ->willReturn([$substitutedUserId]);

        $labelOwnedByUser = new Label(['user_id' => $userId]);
        $labelOwnedBySubstitutedUser = new Label(['user_id' => $substitutedUserId]);
        $labelSharedToUser = new Label([
            'user_id' => $otherUserId,
            'sharing_users' => (string) $userId,
        ]);
        $labelSharedToSubstitutedUser = new Label([
            'user_id' => $otherUserId,
            'sharing_users' => (string) $substitutedUserId,
        ]);
        $labelNotAccessibleToUser = new Label([
            'user_id' => $otherUserId,
            'sharing_users' => '',
        ]);

        return [
            'user with all labels access' => [new Label(), $userWithAllLabelAccess, true],
            'label owned by user' => [$labelOwnedByUser, $user, true],
            'label owned by substituted user' => [$labelOwnedBySubstitutedUser, $user, true],
            'label shared to user' => [$labelSharedToUser, $user, true],
            'label shared to substituted user' => [$labelSharedToSubstitutedUser, $user, true],
            'label not accessible to user' => [$labelNotAccessibleToUser, $user, false],
        ];
    }

    /**
     * @param Label $label
     * @param int $expectedArrayLength
     * @return void
     * @throws InvalidArgumentException
     *
     * @dataProvider provideSharedLabels
     */
    public function testGetSharingUsers(Label $label, int $expectedArrayLength): void
    {
        $users = $label->getSharingUsers();

        self::assertIsArray($users);
        self::assertCount($expectedArrayLength, $users);

        foreach ($users as $user) {
            self::assertInstanceOf(\Velis\User::class, $user);
        }
    }

    /**
     * @return array
     * @throws NoColumnsException
     */
    public function provideSharedLabels(): array
    {
        return [
            [new Label(['sharing_users' => '1,3,5']), 3],
            [new Label(['sharing_users' => '']), 0],
        ];
    }

    /**
     * @param Label $label
     * @param int $expectedArrayLength
     * @return void
     *
     * @dataProvider provideSharedLabels
     */
    public function testGetSharingUserIds(Label $label, int $expectedArrayLength): void
    {
        $userIds = $label->getSharingUserIds();

        self::assertIsArray($userIds);
        self::assertCount($expectedArrayLength, $userIds);

        foreach ($userIds as $userId) {
            self::assertIsInt($userId);
        }
    }
}
