<?php declare(strict_types = 1);

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

use idoit\Module\Cmdb\Component\SyncTemplate\SyncTemplate;
use idoit\Module\SyneticsFlows\Automation\Action\ExecutionInfo\CreateObjectInfo;
use idoit\Module\SyneticsFlows\Automation\Action\ExecutionResult\ErrorExecutionResult;
use idoit\Module\SyneticsFlows\Automation\Action\ExecutionResult\ExecutionResult;
use idoit\Module\SyneticsFlows\Automation\Action\ExecutionResult\ObjectCreatedResult;
use idoit\Module\SyneticsFlows\Automation\Action\ExecutionResult\ValidationError;
use idoit\Module\SyneticsFlows\Automation\Action\ExecutionResult\ValidationErrorResult;
use idoit\Module\SyneticsFlows\Automation\Execution;
use isys_application;
use isys_auth;
use isys_auth_cmdb_object_types;

class CreateObjectExecution implements PerformExecution
{
    public function __construct(private ApplyCategoryChanges $applyCategoryChanges, private ValidateCategoryChanges $validateCategoryChanges)
    {
    }

    public function perform(Execution $execution): ExecutionResult
    {
        $parameters = $execution->getExecution();
        if (!($parameters instanceof CreateObjectInfo)) {
            return new ErrorExecutionResult('Unsupported execution');
        }

        $allowedObjectTypes = isys_auth_cmdb_object_types::instance()->get_allowed_objecttypes(isys_auth::CREATE);

        if (!in_array($parameters->getObjectTypeId(), $allowedObjectTypes)) {
            $lang = \isys_application::instance()->container->get('language');

            return new ErrorExecutionResult(sprintf(
                $lang->get('LC__AUTH__CMDB_EXCEPTION__MISSING_CREATE_RIGHT_FOR_OBJ_TYPE'),
                $lang->get(isys_application::instance()->container->get('cmdb_dao')
                    ->get_objtype_name_by_id_as_string($parameters->getObjectTypeId()))
            ));
        }
        $syncTemplate = SyncTemplate::factory($parameters->getObjectTypeId(), $parameters->getTitle());
        $syncTemplate->create();
        $objectId = $syncTemplate->getObjectId();
        $objectTitle = $syncTemplate->getObjectTitle();
        $changes = $parameters->getChanges();
        $validationErrors = [];

        // Validate all data beforehand
        foreach ($changes as $change) {
            $errors = $this->validateCategoryChanges->validateChange($objectId, $change);
            if (is_array($errors)) {
                foreach ($errors as $field => $error) {
                    $validationErrors[] = new ValidationError($change->getCategoryId(), $field, $error, "$objectId");
                }
            }
        }

        if (!empty($validationErrors)) {
            return new ValidationErrorResult($validationErrors);
        }

        foreach ($changes as $change) {
            $this->applyCategoryChanges->applyChange((int)$objectId, $change);
        }

        return new ObjectCreatedResult("$objectId", $objectTitle);
    }

    public function supports(Execution $execution): bool
    {
        return $execution->getExecution() instanceof CreateObjectInfo;
    }
}
