<?php

namespace App\Tests\Unit\Service\Dolibarr;

use App\Service\Dolibarr\DolibarrApiService;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class DolibarrApiServiceTest extends TestCase
{
    private MockObject | HttpClientInterface $client;

    public function setUp(): void {
        $this->client = $this->getMockBuilder(HttpClientInterface::class)
            ->disableOriginalConstructor()
            ->getMock();
    }

    /**
     * @see DolibarrApiService::getSociety()
     */
    public function testGetSociety(): void {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getSociety'])
            ->getMock();

        $organizationId = 123;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("thirdparties", [ "limit" => "1", "sqlfilters" => "ref_int=" . $organizationId])
            ->willReturn([['id' => 1]]); // dummy non-empty data

        $society = $dolibarrApiService->getSociety($organizationId);

        $this->assertEquals(['id' => 1], $society);
    }

    /**
     * @see DolibarrApiService::getActiveContract()
     */
    public function testGetActiveContract(): void {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getActiveContract'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("contracts", ["limit" => "1", "sqlfilters" => "statut=1", "thirdparty_ids" => $socId])
            ->willReturn([['id' => 1]]); // dummy non-empty data

        $this->assertEquals(['id' => 1], $dolibarrApiService->getActiveContract($socId));
    }

    /**
     * @see DolibarrApiService::getActiveContract()
     */
    public function testGetActiveContractMissing(): void {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getActiveContract'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("contracts", ["limit" => "1", "sqlfilters" => "statut=1", "thirdparty_ids" => $socId])
            ->willThrowException(new HttpException(404));

        $this->assertEquals(null, $dolibarrApiService->getActiveContract($socId));
    }

    /**
     * @see DolibarrApiService::getActiveContract()
     */
    public function testGetActiveContractError(): void {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getActiveContract'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("contracts", ["limit" => "1", "sqlfilters" => "statut=1", "thirdparty_ids" => $socId])
            ->willThrowException(new HttpException(500));

        $this->expectException(HttpException::class);

        $dolibarrApiService->getActiveContract($socId);
    }

    /**
     * @see DolibarrApiService::getBills()
     */
    public function testGetBills(): void {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getBills'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("invoices", ["sortfield" => "datef", "sortorder" => "DESC", "limit" => 5, "sqlfilters" => "fk_soc=" . $socId])
            ->willReturn([['id' => 10], ['id' => 20]]);

        $this->assertEquals([['id' => 10], ['id' => 20]], $dolibarrApiService->getBills($socId));
    }

    /**
     * @see DolibarrApiService::getBills()
     */
    public function testGetBillsMissing(): void {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getBills'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("invoices", ["sortfield" => "datef", "sortorder" => "DESC", "limit" => 5, "sqlfilters" => "fk_soc=" . $socId])
            ->willThrowException(new HttpException(404));

        $this->assertEquals([], $dolibarrApiService->getBills($socId));
    }

    /**
     * @see DolibarrApiService::getBills()
     */
    public function testGetBillsError(): void {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getBills'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("invoices", ["sortfield" => "datef", "sortorder" => "DESC", "limit" => 5, "sqlfilters" => "fk_soc=" . $socId])
            ->willThrowException(new HttpException(500));

        $this->expectException(HttpException::class);

        $dolibarrApiService->getBills($socId);
    }

    /**
     * @see DolibarrApiService::getAllClients()
     */
    public function testGetAllClients(): void
    {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getAllClients'])
            ->getMock();

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("thirdparties", ["limit" => "1000000", "sqlfilters" => "client=1"])
            ->willReturn([['id' => 10], ['id' => 20]]);

        $this->assertEquals([['id' => 10], ['id' => 20]], $dolibarrApiService->getAllClients());
    }

    /**
     * @see DolibarrApiService::getContacts()
     */
    public function testGetContacts(): void
    {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getContacts'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("contacts", ['limit' => 1000, 'thirdparty_ids' => $socId])
            ->willReturn([['id' => 10], ['id' => 20]]);

        $this->assertEquals([['id' => 10], ['id' => 20]], $dolibarrApiService->getContacts($socId));
    }

    /**
     * @see DolibarrApiService::getContacts()
     */
    public function testGetContactsMissing(): void {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getContacts'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("contacts", ['limit' => 1000, 'thirdparty_ids' => $socId])
            ->willThrowException(new HttpException(404));

        $this->assertEquals([], $dolibarrApiService->getContacts($socId));
    }

    /**
     * @see DolibarrApiService::getContacts()
     */
    public function testGetContactsError(): void {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getContacts'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("contacts", ['limit' => 1000, 'thirdparty_ids' => $socId])
            ->willThrowException(new HttpException(500));


        $this->expectException(HttpException::class);

        $dolibarrApiService->getContacts($socId);
    }

    /**
     * @see DolibarrApiService::getActiveOpentalentContacts()
     */
    public function testGetActiveOpentalentContacts(): void
    {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getActiveOpentalentContacts'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("contacts?limit=1000&t.statut=1&thirdparty_ids=" . $socId . "&sqlfilters=(te.2iopen_person_id%3A%3E%3A0)")
            ->willReturn([['id' => 10], ['id' => 20]]);

        $this->assertEquals([['id' => 10], ['id' => 20]], $dolibarrApiService->getActiveOpentalentContacts($socId));
    }

    /**
     * @see DolibarrApiService::getActiveOpentalentContacts()
     */
    public function testGetActiveOpentalentContactsMissing(): void {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getActiveOpentalentContacts'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("contacts?limit=1000&t.statut=1&thirdparty_ids=" . $socId . "&sqlfilters=(te.2iopen_person_id%3A%3E%3A0)")
            ->willThrowException(new HttpException(404));

        $this->assertEquals([], $dolibarrApiService->getActiveOpentalentContacts($socId));
    }

    /**
     * @see DolibarrApiService::getActiveOpentalentContacts()
     */
    public function testGetActiveOpentalentContactsError(): void {
        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getActiveOpentalentContacts'])
            ->getMock();

        $socId = 1;

        $dolibarrApiService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with("contacts?limit=1000&t.statut=1&thirdparty_ids=" . $socId . "&sqlfilters=(te.2iopen_person_id%3A%3E%3A0)")
            ->willThrowException(new HttpException(500));

        $this->expectException(HttpException::class);

        $dolibarrApiService->getActiveOpentalentContacts($socId);
    }
}
