<?php

declare(strict_types=1);

namespace Apexl\Tests\User\FeatureTests;

use apexl\Io\exceptions\RecordNotFoundException;
use apexl\Io\modules\jobs\Entity\QueueJob;
use apexl\Io\TestInfrastructure\FeatureTest;
use app\module\newtonsTrailers\Enum\SyncAction;
use app\module\newtonsTrailers\Job\EtlSyncJob;
use app\module\newtonsTrailers\Service\SuppliedKeyFromHeader;
use PHPUnit\Framework\Attributes\Test;
use function apexl\Io\config;

final class SyncTest extends FeatureTest
{
    private const string ENDPOINT__SYNC = '/webhook/sync';

    #[Test]
    public function failsWithoutSyncKey(): void
    {
        $data = $this->post(self::ENDPOINT__SYNC, [
            'body' => $this->body()
        ], expectCode: 403);

        $this->assertArrayHasKey('error', $data);
        $this->assertSame('No sync key present', $data['error']);
    }

    private function body(array $attr = [], array $data = ['foo' => 'bar']): array
    {
        return [
            ...[
                'sequence' => $this->faker->numberBetween(),
                'date' => $this->faker->date('Y-m-d H:i:s'),
                'table' => $this->faker->word(),
                'ref' => $this->faker->numberBetween(),
                'action' => $this->faker->randomElement(SyncAction::class)->name,
                'data' => $data,
            ],
            ...$attr,
        ];
    }

    #[Test]
    public function failsWithIncorrectSyncKey(): void
    {
        $data = $this->post(self::ENDPOINT__SYNC, [
            'body' => $this->body()
        ], [
            SuppliedKeyFromHeader::HEADER__SYNC_KEY => 'this-key-is-incorrect',
        ], expectCode: 401);

        $this->arrayHasKey('error', $data);
        $this->assertSame('Supplied key does not match configured key', $data['error']);
    }

    #[Test]
    public function addsInsertJob(): void
    {
        $ref = $this->faker->numberBetween();

        $body = $this->body([
            'table' => 'about_us',
            'action' => SyncAction::INSERT->name,
            'ref' => $ref,
            'data' => [
                'ref' => $ref,
                'name' => $this->faker->text(50),
                'live' => $this->faker->boolean() ? 1 : 0,
                'sticky' => $this->faker->boolean() ? 1 : 0,
                'language_meta' => $this->faker->languageCode(),
                'details' => $this->faker->randomHtml(),
            ]
        ]);


        $this->post(
            self::ENDPOINT__SYNC,
            $body,
            [
                SuppliedKeyFromHeader::HEADER__SYNC_KEY => config('sync.key'),
            ]
        );

        try {

            $job = QueueJob::from('sequence', $body['sequence']);
            $this->assertInstanceOf(QueueJob::class, $job);

            $this->assertSame($body['sequence'], $job->sequence);
            $this->assertSame(EtlSyncJob::class, $job->handler);
            $this->assertSame(false, $job->locked);
            $this->assertSame(0, $job->attempts);
            $this->assertSame(null, $job->processed);
            $this->assertSame(null, $job->failed);
            $this->assertSame($body['ref'], $job->contents->ref);
            $this->assertSame($body['table'], $job->contents->table);
            $this->assertSame($body['data']['ref'], $job->contents->data['ref']);
            $this->assertSame($body['data']['name'], $job->contents->data['name']);
            $this->assertSame($body['data']['live'], $job->contents->data['live']);
            $this->assertSame($body['data']['sticky'], $job->contents->data['sticky']);
            $this->assertSame($body['data']['language_meta'], $job->contents->data['language_meta']);
            $this->assertSame($body['data']['details'], $job->contents->data['details']);

        } catch (RecordNotFoundException) {
            $this->fail('Job not created');
        }

    }
}
