<?php

namespace KupShop\KafkaBundle\Tests;

use KupShop\KafkaBundle\DBChanges\DBChangeTypeEnum;
use KupShop\KafkaBundle\DBChanges\Util\DBMessageFactory;
use RdKafka\Message;

class DBMessagesTest extends \DatabaseTestCase
{
    /** @var DBMessageFactory */
    private $dbMessageFactory;
    private array $testMessages;

    protected function setUp(): void
    {
        parent::setUp();
        $this->dbMessageFactory = $this->get(DBMessageFactory::class);
        $this->testMessages = json_decode(file_get_contents(__DIR__.'/dbMessagesTestPayloads.json'), true);
    }

    public function testProductsVariationsUpdate()
    {
        $message = $this->dbMessageFactory->create($this->createMessageFromTestData($this->testMessages['variationsUpdate0']));

        self::assertEquals(DBChangeTypeEnum::UPDATE, $message->getEventType());

        self::assertTrue($message->hasValueChanged('in_store'));
        self::assertFalse($message->hasValueChanged('id'));
        self::assertFalse($message->hasValueChanged('title'));
        self::assertTrue($message->hasValueChanged('in_store'));

        self::assertTrue($message->didAnyOfFieldChange(['title', 'in_store']));

        self::assertFalse($message->didAnyOfFieldChange(['aaa', 'bbb']));

        self::assertEquals(309, $message->getValue('in_store'));
        self::assertEquals(1234, $message->getValue('ean'));
        self::assertEquals(['in_store' => 309, 'updated' => '2025-04-29T10:52:10Z', 'delivery_time' => 0, 'ean' => 1234], $message->getChangedValues());
        self::assertEquals(['in_store',  'delivery_time', 'ean', 'updated'], $message->getChangedValuesKeys());

        self::assertFalse($message->hasValueBoolChanged('in_store'));
        self::assertTrue($message->hasValueBoolChanged('delivery_time'));

        self::assertFalse($message->startsWithChanged('id'));
        self::assertTrue($message->startsWithChanged('in'));

        self::assertEquals(312, $message->getPreviousValue('in_store'));
        self::assertEquals('products_variations', $message->getTableName());
    }

    public function testProductsVariationsInsert()
    {
        $message = $this->dbMessageFactory->create($this->createMessageFromTestData($this->testMessages['variationsInsert0']));

        self::assertEquals(DBChangeTypeEnum::INSERT, $message->getEventType());
        self::assertEquals('products_variations', $message->getTableName());

        self::assertNotNull($message->getChangedValues());
        self::assertArraySubset($message->getChangedValues(), $message->getValues());

        self::assertTrue($message->hasValueChanged('in_store'));
        self::assertTrue($message->hasValueChanged('id'));
        self::assertTrue($message->hasValueChanged('title'));

        self::assertTrue($message->didAnyOfFieldChange(['title', 'in_store']));

        self::assertEquals(5, $message->getValue('in_store'));

        self::assertTrue($message->hasValueBoolChanged('delivery_time'));
        self::assertTrue($message->startsWithChanged('in'));

        self::assertEquals([], $message->getPreviousValues());
        self::assertNull($message->getPreviousValue('in_store'));
    }

    public function testProductsVariationsDelete()
    {
        $message = $this->dbMessageFactory->create($this->createMessageFromTestData($this->testMessages['variationsDelete0']));

        self::assertEquals(DBChangeTypeEnum::DELETE, $message->getEventType());
        self::assertEquals('products_variations', $message->getTableName());

        self::assertNotNull($message->getValues());
        self::assertArraySubset($message->getChangedValues(), $message->getValues());

        self::assertTrue($message->hasValueChanged('in_store'));
        self::assertTrue($message->hasValueChanged('id'));
        self::assertTrue($message->hasValueChanged('title'));

        self::assertTrue($message->didAnyOfFieldChange(['title', 'in_store']));

        self::assertEquals(5, $message->getValue('in_store'));

        self::assertTrue($message->hasValueBoolChanged('delivery_time'));
        self::assertTrue($message->startsWithChanged('in'));

        self::assertEquals([], $message->getPreviousValues());
        self::assertNull($message->getPreviousValue('in_store'));
    }

    private function createMessageFromTestData(array $data)
    {
        $message = new Message();

        $message->payload = json_encode($data['payload']);
        $message->headers = [];
        $message->key = 'key';
        $message->offset = 1;
        $message->timestamp = time() * 1000;
        $message->len = strlen($message->payload);
        $message->topic_name = 'test';
        $message->err = 0;
        $message->partition = 0;

        return $message;
    }
}
