<?php

namespace FiloBlu\Esb\Model;

use FiloBlu\Esb\Api\Data\EventConfigurationInterface;
use FiloBlu\Esb\Api\Data\EventConfigurationInterfaceFactory;
use FiloBlu\Esb\Api\EventConfigurationRepositoryInterface;
use FiloBlu\Esb\Api\EventResolverInterface;
use Magento\Framework\Api\Search\SearchCriteriaInterfaceFactory;
use Magento\Framework\Api\SearchResultsInterfaceFactory;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Exception\NoSuchEntityException;
use RuntimeException;

/**
 * Class EventConfigurationRepository
 * @package FiloBlu\Esb\Model
 */
class EventConfigurationRepository extends AbstractSqlRepository implements EventConfigurationRepositoryInterface
{
    /** @var string */
    const TABLE = 'esb_event_configuration';
    /**
     * @var EventConfigurationInterfaceFactory
     */
    private $eventConfigurationFactory;
    /**
     * @var EventResolverInterface
     */
    private $eventResolver;

    /**
     * EventConfigurationRepository constructor.
     * @param ResourceConnection $resourceConnection
     * @param SearchCriteriaInterfaceFactory $searchCriteriaFactory
     * @param SearchResultsInterfaceFactory $searchResultsFactory
     * @param EventConfigurationInterfaceFactory $eventConfigurationFactory
     * @param EventResolverInterface $eventResolver
     */
    public function __construct(
        ResourceConnection $resourceConnection,
        SearchCriteriaInterfaceFactory $searchCriteriaFactory,
        SearchResultsInterfaceFactory $searchResultsFactory,
        EventConfigurationInterfaceFactory $eventConfigurationFactory,
        EventResolverInterface $eventResolver
    ) {
        parent::__construct($resourceConnection, $searchCriteriaFactory, $searchResultsFactory);
        $this->eventConfigurationFactory = $eventConfigurationFactory;
        $this->eventResolver = $eventResolver;
    }

    /**
     * @inheritDoc
     */
    public function getTable(): string
    {
        return self::TABLE;
    }

    /**
     * @inheritDoc
     * @throws NoSuchEntityException
     */
    public function fromRow(array $row)
    {
        /** @var EventConfigurationInterface $event */
        $event = $this->eventConfigurationFactory->create();

        return $event
            ->setLabel($row[EventConfigurationInterface::LABEL] ?? '')
            ->setEventcode($row[EventConfigurationInterface::EVENT_CODE])
            ->setBaseEvent($this->eventResolver->get($row[EventConfigurationInterface::BASE_EVENT]))
            ->setUuid($row[EventConfigurationInterface::UUID])
            ->setId($row[EventConfigurationInterface::ID]);
    }

    /**
     * @inheritDoc
     */
    public function save(EventConfigurationInterface $configuration)
    {
        $connection = $this->resourceConnection->getConnection();
        $table = $connection->getTableName(self::TABLE);

        $event = $configuration->getEventCode();

        if ($event === null && ctype_space($event)) {
            throw new RuntimeException('Could not save event configuration with empty event code');
        }

        $bindings = [
            EventConfigurationInterface::ID => $configuration->getId(),
            EventConfigurationInterface::UUID => $configuration->getUuid(),
            EventConfigurationInterface::LABEL => $configuration->getLabel(),
            EventConfigurationInterface::EVENT_CODE => $configuration->getEventCode(),
            EventConfigurationInterface::BASE_EVENT => $configuration->getBaseEvent()->getUniqueName()
        ];

        if ($configuration->getId()) {
            $connection->update($table, $bindings, $connection->quoteInto(
                sprintf('%s = ?', EventConfigurationInterface::ID),
                $configuration->getId()
            ));
        } else {
            $connection->insert($table, $bindings);
            $configuration->setId($connection->lastInsertId($table));
        }

        return $configuration;
    }

    /**
     * @inheritDoc
     */
    public function delete(EventConfigurationInterface $configuration)
    {
        if (!($id = $configuration->getId())) {
            return;
        }

        $this->deleteById($id);
    }

    /**
     * @inheritDoc
     */
    public function getIdFieldName(): string
    {
        return EventConfigurationInterface::ID;
    }
}
