<?php declare(strict_types = 1);

namespace idoit\Module\SyneticsFlows\Automation\Action\PerformExecution;

use idoit\Module\Cmdb\Component\CategoryChanges\Changes;
use idoit\Module\Cmdb\Component\SyncMerger\Config;
use idoit\Module\Cmdb\Component\SyncMerger\Merger;
use idoit\Module\SyneticsFlows\Automation\Action\ActionType\CmdbChange\CategoryChange;
use idoit\Module\SyneticsFlows\Automation\Action\ActionType\CmdbChange\CmdbChange;
use idoit\Module\SyneticsFlows\Model\CategoryDao;
use isys_cmdb_dao_category;
use isys_cmdb_dao_category_g_custom_fields;
use isys_component_database;
use isys_import_handler_cmdb;

class ApplyCategoryChanges extends AbstractCategoryChanges
{
    public function applyChange(int $objectId, CategoryChange $change): void
    {
        if (!($dao = $this->getDaoOfCategory($change))) {
            return;
        }

        $newCategoryEntry = [
            Config::CONFIG_DATA_ID => null,
            Config::CONFIG_PROPERTIES => $this->preparePropertiesData($change->getChanges()),
        ];

        $mergerData = Merger::instance(Config::instance($dao, $objectId, $newCategoryEntry))->getDataForSync();
        $mode = isys_import_handler_cmdb::C__CREATE;
        if ($mergerData[Config::CONFIG_DATA_ID] !== null) {
            $mode = isys_import_handler_cmdb::C__UPDATE;
        }

        $change = $this->getCategoryChanges($dao, $objectId, $newCategoryEntry);

        $dao->sync($mergerData, $objectId, $mode);

        if ($change && $change->getCurrentReformatedChanges()) {
            \isys_event_manager::getInstance()
                ->triggerCMDBEvent(
                    'C__LOGBOOK_EVENT__CATEGORY_CHANGED',
                    $dao->get_strLogbookSQL(),
                    $objectId,
                    $dao->get_objTypeID($objectId),
                    $dao->getCategoryTitle(),
                    serialize($change->getCurrentReformatedChanges())
                );
        }

    }

    /**
     * @param isys_cmdb_dao_category $dao
     * @param int $objectId
     * @param array $newData
     *
     * @return Changes|null
     */
    private function getCategoryChanges(isys_cmdb_dao_category $dao, int $objectId, array $newData = []): ?Changes
    {
        if (empty($newData)) {
            return null;
        }

        $fakeEntry = [
            Config::CONFIG_DATA_ID => null,
            Config::CONFIG_PROPERTIES => []
        ];
        $currentData = Merger::instance(Config::instance($dao, $objectId, $fakeEntry))->getDataForSync();

        if (isset($newData[Config::CONFIG_PROPERTIES]) && isset($currentData[Config::CONFIG_PROPERTIES])) {
            $currentDataValues = $syncDataValues = [];
            foreach($newData[Config::CONFIG_PROPERTIES] as $index => $value) {
                $syncDataValues[$index] = empty($value['value']) ? null : $value['value'];
            }
            foreach($currentData[Config::CONFIG_PROPERTIES] as $index => $value) {
                $currentDataValues[$index] = $value['value'];
                if (!isset($syncDataValues[$index])) {
                    $syncDataValues[$index] = $value['value'];
                }
            }

            $changes = Changes::instance($dao, $objectId, null, $currentDataValues, $syncDataValues);
            $changes->processChanges();

            return $changes;
        }
        return null;
    }
}
