<?php declare(strict_types = 1);

namespace idoit\Module\SyneticsFlows\Automation\Action\ActionType\IdoitCommand\Option;

use idoit\Module\SyneticsFlows\Automation\Action\ActionType\IdoitCommand\DataSource\DataSource;
use idoit\Module\SyneticsFlows\Serialization\Exclude;
use idoit\Module\SyneticsFlows\Validation\ValidationMessage;
use Symfony\Component\Console\Input\InputInterface;

class DynamicStringMultiSelectOption extends IdoitCliOption implements ValueProviderOption
{
    /**
     * @param string $name
     * @param string $description
     * @param bool $required
     * @param DataSource $dataSource
     * @param array|null $defaultValue
     * @param string $valueSeparator
     */
    public function __construct(
        string $name,
        string $description,
        bool $required,
        #[Exclude]
        private DataSource $dataSource,
        private ?array $defaultValue,
        #[Exclude]
        private string $valueSeparator = ','
    )
    {
        parent::__construct($name, $description, $required);
    }

    public function getValues(array $parameters): array
    {
        return $this->dataSource->getValues($parameters);
    }

    public function validate(mixed $value, array $parameters): array
    {
        $errors = parent::validate($value, $parameters);

        if (!$value) {
            return $errors;
        }

        if (!is_array($value)) {
            return [...$errors, new ValidationMessage([$this->name], 'Value should be in array format.')];
        }

        $sourceValues = array_map(
            fn(SelectOptionValue $optionValue) => $optionValue->getValue(),
            $this->getValues($parameters)
        );

        if ($diff = array_diff($value, $sourceValues)) {
            $errors[] = new ValidationMessage([$this->name], 'The following values are not valid: ' . join(',', $diff));
        }

        return $errors;
    }

    public function getDefaultValue(): ?array
    {
        return $this->defaultValue;
    }

    public function getValueSeparator(): string
    {
        return $this->valueSeparator;
    }

    public function apply(InputInterface $input, mixed $value): void
    {
        $input->setOption($this->name, is_array($value) ? join($this->valueSeparator, $value) : $value);
    }
}