<?php

namespace External\MSSQLBundle\Synchronizers;

use Doctrine\DBAL\Query\QueryBuilder;
use External\MSSQLBundle\Util\MappingTrait;
use External\MSSQLBundle\Util\MoneyConnection;
use KupShop\AdminBundle\Util\ActivityLog;

abstract class BaseSynchronizer implements SynchronizerInterface
{
    use \DatabaseCommunication;
    use MappingTrait;

    protected static $type;
    protected static $priority = 0;

    protected static $selectFields = [];
    protected static $tableName;
    protected static $tableAlias;
    protected static $tableDateColumn = 'Modify_Date';

    protected $config;

    protected $connection;
    protected $fullSync = false;

    protected $tmpLastSync;

    public function __construct(MoneyConnection $connection)
    {
        $this->connection = $connection;
    }

    public static function getType(): ?string
    {
        return static::$type;
    }

    public static function getPriority(): int
    {
        return static::$priority;
    }

    public function setConfig($config): void
    {
        $this->config = $config;
    }

    public function setFullSync(bool $fullSync): void
    {
        $this->fullSync = $fullSync;
    }

    public function getLastSyncDate(): ?int
    {
        $dates = \Settings::getDefault()->money_sync ?? [];

        $this->tmpLastSync = time() - (60 * 5);

        return $dates[static::getType()] ?? null;
    }

    public function updateLastSyncDate(): void
    {
        $dbcfg = \Settings::getDefault();

        $dates = $dbcfg->money_sync ?? [];
        $dates[static::getType()] = $this->tmpLastSync ? $this->tmpLastSync : (time() - (60 * 5));

        $dbcfg->saveValue('money_sync', $dates);
        \Settings::clearCache(true);
    }

    public function sync(bool $transactional = true): void
    {
        try {
            if ($transactional) {
                sqlGetConnection()->transactional(
                    function () {
                        $this->process(
                            $this->getLastSyncDate()
                        );

                        $this->updateLastSyncDate();
                    }
                );
            } else {
                $this->process(
                    $this->getLastSyncDate()
                );
                $this->updateLastSyncDate();
            }
        } catch (\PDOException $e) {
            addActivityLog(
                ActivityLog::SEVERITY_ERROR,
                ActivityLog::TYPE_SYNC,
                'Selhalo spojení s databází ERP, pokud problém přetrvává, kontaktujte poskytovatele',
                ['message' => $e->getMessage()]
            );
        }
    }

    protected function getQueryBuilder(?int $lastSyncTime = null): QueryBuilder
    {
        $qb = $this->connection->getQueryBuilder()
            ->from(static::$tableName, static::$tableAlias);

        foreach (static::$selectFields as $field => $alias) {
            $qb->addSelect($field.' as '.$alias);
        }

        if ($lastSyncTime && !$this->fullSync) {
            $datetime = (new \DateTime())->setTimestamp($lastSyncTime);
            $qb->andWhere($this->getDateColumn().' >= :last_sync_date')
                ->setParameter('last_sync_date', $datetime->format('Y-m-d H:i:s'));
        }

        return $qb;
    }

    protected function getDateColumn(): string
    {
        return static::$tableAlias ? static::$tableAlias.'.'.static::$tableDateColumn : static::$tableDateColumn;
    }

    abstract protected function process(?int $lastSyncTime = null): void;
}
