<?php
namespace Tests\Unit;

use Api\Controllers\V1\ElixFormsController;
use Api\Core\Config;
use Api\Core\Request;
use Api\Core\Response;
use ElixForms\Auth\ElixFormsApiClient;
use ElixForms\Auth\ElixFormsAuthenticationClient;
use PHPUnit\Framework\TestCase;

final class ElixFormsControllerTest extends TestCase
{
    public function testSearchInstancesReturnsOnlyMatchingInstances(): void
    {
        $authenticationClient = new class extends ElixFormsAuthenticationClient {
            public function __construct()
            {
            }

            public function login(string $username, string $password): string
            {
                return 'token';
            }
        };
        $apiClient = new class extends ElixFormsApiClient {
            public function __construct()
            {
            }

            public function lookupByStatus(
                string $moduleTag,
                string $authToken,
                string $username,
                ?int $status = null
            ): array
            {
                return [
                    ['idDomanda' => 10],
                    ['requestId' => 20],
                    ['idRequest' => 30],
                ];
            }

            public function getExportTags(
                $requestId,
                string $moduleTag,
                string $authToken,
                string $username,
                string $exportGroup = 'API'
            ): array
            {
                if ($exportGroup !== 'CUSTOM') {
                    throw new \RuntimeException('exportGroup non inoltrato al client.');
                }

                $tags = [
                    10 => [
                        'name' => 'contratto.altro',
                        'value' => 'Il contratto ABC-123 è presente',
                    ],
                    20 => [
                        'name' => 'contratto.id',
                        'value' => 'Il contratto ABC-123 è presente',
                    ],
                    30 => [
                        'name' => 'contratto.id',
                        'value' => 'Altro valore',
                    ],
                ];

                return [$tags[$requestId]];
            }
        };
        $config = new class extends Config {
            public function secret($key, $default = null)
            {
                return $key === 'elixforms_api_username' ? 'user' : 'password';
            }
        };
        $request = new class extends Request {
            public function query()
            {
                return [
                    'moduleTag' => 'MODULO',
                    'fieldName' => 'contratto.id',
                    'fieldValue' => 'abc-123',
                    'exportGroup' => ' CUSTOM ',
                ];
            }
        };
        $response = new CapturingResponse();
        $controller = new ElixFormsController($authenticationClient, $apiClient, $config);

        try {
            $controller->searchInstances($request, $response);
            self::fail('La risposta avrebbe dovuto interrompere il flusso del test.');
        } catch (CapturedResponseException $exception) {
            self::assertSame(200, $exception->status);
            self::assertSame([['requestId' => 20]], $exception->payload);
        }
    }

    public function testSearchInstancesRejectsMissingParameters(): void
    {
        $authenticationClient = new class extends ElixFormsAuthenticationClient {
            public function __construct()
            {
            }
        };
        $apiClient = new class extends ElixFormsApiClient {
            public function __construct()
            {
            }
        };
        $config = new Config();
        $request = new class extends Request {
            public function query()
            {
                return ['moduleTag' => 'MODULO'];
            }
        };
        $controller = new ElixFormsController($authenticationClient, $apiClient, $config);

        try {
            $controller->searchInstances($request, new CapturingResponse());
            self::fail('La risposta avrebbe dovuto interrompere il flusso del test.');
        } catch (CapturedResponseException $exception) {
            self::assertSame(400, $exception->status);
        }
    }
}

final class CapturingResponse extends Response
{
    public function json($data, $status = 200)
    {
        throw new CapturedResponseException($data, $status);
    }
}

final class CapturedResponseException extends \RuntimeException
{
    public $payload;
    public int $status;

    public function __construct($payload, int $status)
    {
        parent::__construct('Response captured');
        $this->payload = $payload;
        $this->status = $status;
    }
}
