<?php declare(strict_types = 1);

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

use idoit\Module\SyneticsFlows\Automation\Action\ActionType\ActionType;
use idoit\Module\SyneticsFlows\Automation\Action\ActionType\ChangeObjectAction;
use idoit\Module\SyneticsFlows\Automation\Action\ActionType\CmdbChange\CurrentObjectScope;
use idoit\Module\SyneticsFlows\Automation\Action\ActionType\CmdbChange\ObjectIdsScope;
use idoit\Module\SyneticsFlows\Automation\Action\ExecutionInfo\ExecutionInfo;
use idoit\Module\SyneticsFlows\Automation\Action\ExecutionInfo\UpdateDataInfo;
use idoit\Module\SyneticsFlows\Automation\Automation;
use idoit\Module\SyneticsFlows\Automation\Trigger\Invocation\Invocation;
use idoit\Module\SyneticsFlows\Automation\Trigger\Invocation\ObjectContext;
use idoit\Module\SyneticsFlows\Template\TemplateFactory;

class UpdateDataFactory implements ExecutionFactory
{
    public function __construct(private TemplateFactory $factory, private ProcessCategoryChanges $processCategoryChanges)
    {
    }

    public function createExecution(Invocation $invocation, Automation $automation, ActionType $actionType): ?ExecutionInfo
    {
        if (!$actionType instanceof ChangeObjectAction) {
            return null;
        }

        $categoryChanges = $actionType->getChanges();
        $objectIds = $this->getObjectIds($actionType, $invocation);
        $template = $this->factory->forInvocation($invocation, $automation);

        return new UpdateDataInfo($objectIds, $this->processCategoryChanges->process($template, $categoryChanges));
    }

    private function getObjectIds(ChangeObjectAction $action, Invocation $invocation): array
    {
        $scope = $action->getScope();

        if ($scope instanceof CurrentObjectScope) {
            $context = $invocation->getContext();

            if ($context instanceof ObjectContext) {
                return [$context->getObjectId()];
            }
        }

        if ($scope instanceof ObjectIdsScope) {
            return $scope->getIds();
        }

        return [];
    }

    public function supports(ActionType $actionType): bool
    {
        return $actionType instanceof ChangeObjectAction;
    }
}
