<?php

namespace App\Tests\Service;

use App\Service\SiretService;
use PHPUnit\Framework\TestCase;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

class SiretServiceTest extends TestCase
{
    public function testLookupReturnsDataWithLabels(): void
    {
        $response = $this->createMock(ResponseInterface::class);
        $response->method('toArray')->willReturn([
            'results' => [[
                'nom_complet' => 'E-COSPLAY',
                'nature_juridique' => '9220',
                'activite_principale' => '93.29Z',
                'siren' => '943121517',
            ]],
        ]);

        $httpClient = $this->createMock(HttpClientInterface::class);
        $httpClient->method('request')->willReturn($response);

        $cache = $this->createMock(CacheInterface::class);
        $cache->method('get')->willReturnCallback(fn (string $key, callable $callback) => $callback($this->createMock(ItemInterface::class)));

        $projectDir = \dirname(__DIR__, 2);
        $service = new SiretService($httpClient, $cache, $projectDir);
        $data = $service->lookup('94312151700016');

        self::assertNotNull($data);
        self::assertSame('E-COSPLAY', $data['nom_complet']);
        self::assertSame('Association declaree', $data['libelle_nature_juridique']);
        self::assertNotNull($data['libelle_activite_principale']);
    }

    public function testLookupReturnsNullWhenNotFound(): void
    {
        $response = $this->createMock(ResponseInterface::class);
        $response->method('toArray')->willReturn(['results' => []]);

        $httpClient = $this->createMock(HttpClientInterface::class);
        $httpClient->method('request')->willReturn($response);

        $cache = $this->createMock(CacheInterface::class);
        $cache->method('get')->willReturnCallback(fn (string $key, callable $callback) => $callback($this->createMock(ItemInterface::class)));

        $service = new SiretService($httpClient, $cache, \dirname(__DIR__, 2));

        self::assertNull($service->lookup('00000000000000'));
    }

    public function testLookupReturnsNullOnApiError(): void
    {
        $httpClient = $this->createMock(HttpClientInterface::class);
        $httpClient->method('request')->willThrowException(new \RuntimeException('API down'));

        $cache = $this->createMock(CacheInterface::class);
        $cache->method('get')->willReturnCallback(fn (string $key, callable $callback) => $callback($this->createMock(ItemInterface::class)));

        $service = new SiretService($httpClient, $cache, \dirname(__DIR__, 2));

        self::assertNull($service->lookup('00000000000000'));
    }

    public function testGetNatureJuridiqueLabel(): void
    {
        $httpClient = $this->createMock(HttpClientInterface::class);
        $cache = $this->createMock(CacheInterface::class);
        $service = new SiretService($httpClient, $cache, \dirname(__DIR__, 2));

        self::assertSame('Association declaree', $service->getNatureJuridiqueLabel('9220'));
        self::assertSame('SAS', $service->getNatureJuridiqueLabel('5710'));
        self::assertNull($service->getNatureJuridiqueLabel('0000'));
    }

    public function testGetNafLabel(): void
    {
        $httpClient = $this->createMock(HttpClientInterface::class);
        $cache = $this->createMock(CacheInterface::class);
        $service = new SiretService($httpClient, $cache, \dirname(__DIR__, 2));

        self::assertNotNull($service->getNafLabel('93.29Z'));
        self::assertNull($service->getNafLabel('XX.XXX'));
    }

    public function testLookupRnaReturnsData(): void
    {
        $response = $this->createMock(ResponseInterface::class);
        $response->method('toArray')->willReturn([
            'records' => [[
                'fields' => [
                    'numero_rna' => 'W022006988',
                    'objet' => 'promotion du cosplay',
                    'association_type_libelle' => 'Associations loi du 1er juillet 1901',
                ],
            ]],
        ]);

        $httpClient = $this->createMock(HttpClientInterface::class);
        $httpClient->method('request')->willReturn($response);

        $cache = $this->createMock(CacheInterface::class);
        $cache->method('get')->willReturnCallback(fn (string $key, callable $callback) => $callback($this->createMock(ItemInterface::class)));

        $service = new SiretService($httpClient, $cache, \dirname(__DIR__, 2));
        $data = $service->lookupRna('W022006988');

        self::assertNotNull($data);
        self::assertSame('W022006988', $data['numero_rna']);
        self::assertSame('promotion du cosplay', $data['objet']);
    }

    public function testLookupRnaReturnsNullWhenNotFound(): void
    {
        $response = $this->createMock(ResponseInterface::class);
        $response->method('toArray')->willReturn(['records' => []]);

        $httpClient = $this->createMock(HttpClientInterface::class);
        $httpClient->method('request')->willReturn($response);

        $cache = $this->createMock(CacheInterface::class);
        $cache->method('get')->willReturnCallback(fn (string $key, callable $callback) => $callback($this->createMock(ItemInterface::class)));

        $service = new SiretService($httpClient, $cache, \dirname(__DIR__, 2));

        self::assertNull($service->lookupRna('W000000000'));
    }

    public function testClearCacheWithRna(): void
    {
        $httpClient = $this->createMock(HttpClientInterface::class);
        $cache = $this->createMock(CacheInterface::class);
        $cache->expects(self::exactly(2))->method('delete');

        $service = new SiretService($httpClient, $cache, \dirname(__DIR__, 2));
        $service->clearCache('12345678901234', 'W022006988');
    }

    public function testGetNafLabelMissingFile(): void
    {
        $httpClient = $this->createMock(HttpClientInterface::class);
        $cache = $this->createMock(CacheInterface::class);
        $service = new SiretService($httpClient, $cache, '/nonexistent');

        self::assertNull($service->getNafLabel('93.29Z'));
    }
}
