<?php

declare(strict_types=1);

namespace KupShop\KafkaBundle\DBChanges\MessageHandlers;

use KupShop\KafkaBundle\DBChanges\MessageTypes\DBGenericMessage;
use KupShop\KafkaBundle\DBChanges\MessageTypes\DBMsgProduct;
use KupShop\KafkaBundle\DBChanges\Util\DBMessageFactory;
use Psr\Log\LoggerInterface;
use RdKafka\Message;
use Symfony\Contracts\Service\Attribute\Required;

/**
 * @method handleProducts(DBMsgProduct $message)
 * @method handleProductsVariations(DBGenericMessage $message)
 * @method handleParametersProducts(DBGenericMessage $message)
 * @method handleProductsInSections(DBGenericMessage $message)
 * @method handlePricelistsProducts(DBGenericMessage $message)
 * @method handlePriceLevelsProducts(DBGenericMessage $message)
 * @method handleProductsOfSuppliers(DBGenericMessage $message)
 * @method handleProductLabelsRelation(DBGenericMessage $message)
 * @method handleStoresItems(DBGenericMessage $message)
 * @method handleProductsInSectionsPositions(DBGenericMessage $message)
 * @method handleProductsVariationsChoicesCategorization(DBGenericMessage $message)
 * @method handlePhotosProductsRelation(DBGenericMessage $message)
 */
abstract class DBMessageAbstractHandler implements DBMessageHandlerInterface
{
    #[Required]
    public DBMessageFactory $dbMessageFactory;

    #[Required]
    public LoggerInterface $logger;

    abstract public function handleDefault(DBGenericMessage $message): void;

    public function createMessageAndHandle(Message $rawMessage): void
    {
        $message = $this->dbMessageFactory->create($rawMessage);

        $tableMethod = 'handle'.$this->tableCamelize($message->getTableName());

        if (method_exists($this, $tableMethod)) {
            $this->{$tableMethod}($message);
        } else {
            $this->handleDefault($message);
        }
    }

    private function tableCamelize($input, $separator = '_')
    {
        return str_replace($separator, '', ucwords($input, $separator));
    }

    /**
     * Use in synchronization tasks. Service instances are persisted between runs.
     *
     * @return $this
     */
    public function newInstance(): self
    {
        return clone $this;
    }
}
