<?php

use CTApi\CTClient;
use CTApi\CTConfig;
use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\ResponseInterface;

it('syncs mocked future events and song shape through the CTS pipeline', function () {
    $eventsPayload = [
        'data' => [
            [
                'domainIdentifier' => '100',
                'title' => 'Gottesdienst Sonntag',
                'startDate' => '2026-03-08T10:00:00+00:00',
                'note' => 'Probe',
            ],
        ],
        'meta' => [
            'pagination' => [
                'lastPage' => 1,
            ],
        ],
    ];

    $songPayload = [
        'data' => [
            'songId' => '1',
            'name' => 'Way Maker',
            'ccli' => '7115744',
            'arrangements' => [
                ['id' => '11', 'name' => 'Normal', 'isDefault' => true],
            ],
            'lyrics' => [
                'type' => 'text',
                'cclid' => '7115744',
                'lyricParts' => [
                    ['key' => 'v1', 'text' => 'Du bist hier'],
                ],
            ],
        ],
    ];

    $mockClient = new CtsApiSpikeMockClient([
        '/api/events' => [new Response(200, [], json_encode($eventsPayload, JSON_THROW_ON_ERROR))],
        '/api/songs/1' => [new Response(200, [], json_encode($songPayload, JSON_THROW_ON_ERROR))],
    ]);

    $result = \App\Cts\CtsApiSpikeSync::run(
        apiUrl: 'https://example.church.tools',
        apiToken: 'token-abc',
        fromDate: '2026-03-01',
        songId: 1,
        client: $mockClient,
    );

    expect($result['events']['count'])->toBe(1)
        ->and($result['events']['first']['title'])->toBe('Gottesdienst Sonntag')
        ->and($result['song']['hasCcli'])->toBeTrue()
        ->and($result['song']['hasLyrics'])->toBeTrue()
        ->and($result['song']['arrangements_count'])->toBe(1)
        ->and($result['auth']['method'])->toBe('setApiKey');

    $eventsCall = $mockClient->firstCallFor('GET', '/api/events');

    expect($eventsCall['options']['query']['from'])->toBe('2026-03-01')
        ->and($eventsCall['options']['query']['page'])->toBe(1)
        ->and(CTConfig::getRequestConfig()['query']['login_token'])->toBe('token-abc');
});

it('returns auth blocker when API token is missing', function () {
    $result = \App\Cts\CtsApiSpikeSync::run(
        apiUrl: 'https://example.church.tools',
        apiToken: '',
        fromDate: '2026-03-01',
        songId: 1,
        client: new CtsApiSpikeMockClient([]),
    );

    expect($result['auth']['ok'])->toBeFalse()
        ->and($result['auth']['blocker'])->toContain('CTS_API_TOKEN');
});

final class CtsApiSpikeMockClient extends CTClient
{
    private array $responsesByUri;

    private array $calls = [];

    public function __construct(array $responsesByUri)
    {
        $this->responsesByUri = $responsesByUri;
    }

    public function get($uri, array $options = []): ResponseInterface
    {
        $this->calls[] = [
            'method' => 'GET',
            'uri' => $uri,
            'options' => $options,
        ];

        if (! isset($this->responsesByUri[$uri]) || $this->responsesByUri[$uri] === []) {
            return new Response(404, [], json_encode(['data' => []], JSON_THROW_ON_ERROR));
        }

        return array_shift($this->responsesByUri[$uri]);
    }

    public function firstCallFor(string $method, string $uri): array
    {
        foreach ($this->calls as $call) {
            if ($call['method'] === $method && $call['uri'] === $uri) {
                return $call;
            }
        }

        throw new RuntimeException("No call recorded for {$method} {$uri}");
    }
}
