<?php

namespace Opentalent\OtCore\Tests\Unit\Domain\Repository;

use GuzzleHttp\Client;
use Nimut\TestingFramework\TestCase\UnitTestCase;
use Opentalent\OtCore\Domain\Repository\BaseApiRepository;
use Opentalent\OtCore\Service\OpentalentApiService;
use Opentalent\OtCore\Tests\Unit\Fixtures\ApiResponseFixtures;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use ReflectionClass;
use TYPO3\CMS\Core\Core\ApplicationContext;

/**
 * Base class for BaseApiRepositoryTest and its subclasses
 *
 * @package Opentalent\OtCore\Tests\Unit\Repository
 */
abstract class AbstractApiRepositoryTestCase extends UnitTestCase
{
    use ProphecyTrait;

    const TESTED_CLASS = '';

    protected $context;
    /**
     * @var ApiResponseFixtures
     */
    protected $fixture;
    /**
     * @var object
     */
    protected $repository;
    /**
     * @var \Prophecy\Prophecy\ObjectProphecy
     */
    protected $client;

    protected $service;

    public function setUp(): void
    {
        // mock the application context
        $this->context = $this->prophesize(ApplicationContext::class);
        $this->context->isProduction()->willReturn(false);
        $this->context->isDevelopment()->willReturn(false);
        $this->context->isTesting()->willReturn(true);

        $this->client = $this->prophesize(Client::class);
        $this->service = new OpentalentApiService(
            $this->client->reveal(),
            $this->context->reveal()
        );

        $repositoryClass = new ReflectionClass(static::TESTED_CLASS);
        foreach ($repositoryClass->getMethods() as $method) {
            $method->setAccessible(true);
        }
        $this->repository = $repositoryClass->newInstanceArgs([$this->service]);

        $this->fixture = new ApiResponseFixtures();
    }

    protected function injectClientFor($uri, $http_method='GET') {
        // mock the Guzzle client
        $willReturn = $this->fixture->get($uri);

        $client = $this->prophesize(Client::class);
        $client->request($http_method, $uri, [])
            ->shouldBeCalled()
            ->willReturn($willReturn);

        $reflectionObject = new \ReflectionObject($this->service);
        $reflectionMethod = $reflectionObject->getMethod('injectClient');
        $reflectionMethod->setAccessible(true);

        $reflectionMethod->invokeArgs($this->service, [$client->reveal()]);
    }

    protected function callMemberToObject(array $record) {
        $reflectionObject = new \ReflectionObject($this->repository);
        $reflectionMethod = $reflectionObject->getMethod('memberToObject');
        $reflectionMethod->setAccessible(true);

        return $reflectionMethod->invokeArgs($this->repository, [$record]);
    }
}
