<?php

declare(strict_types=1);

namespace ShopManagerPro\Filters\DTO\Generated;

class FilterConditionsItem {
	private static array $schema = ['type' => 'object', 'additionalProperties' => false, 'required' => ['field', 'operator', 'value', 'not', 'combinator', 'enabled'], 'properties' => ['field' => ['type' => 'object', 'additionalProperties' => false, 'required' => ['type', 'key'], 'properties' => ['type' => ['type' => 'string', 'enum' => ['acf', 'basic', 'defaultTaxonomy', 'germanMarket', 'customMeta', 'productAttribute']], 'key' => ['type' => 'string']]], 'operator' => ['type' => 'string', 'enum' => ['contains', 'empty', 'ends_with', 'equals', 'greater_than_or_equal', 'greater_than', 'in', 'less_than_or_equal', 'less_than', 'starts_with']], 'value' => ['type' => ['string', 'number', 'boolean', 'array', 'null']], 'not' => ['type' => 'boolean'], 'combinator' => ['type' => 'string', 'enum' => ['AND', 'OR']], 'enabled' => ['type' => 'boolean']]];
	private FilterConditionsItemField $field;
	private FilterConditionsItemOperator $operator;
	private $value;
	private bool $not;
	private FilterConditionsItemCombinator $combinator;
	private bool $enabled;

	public function __construct(FilterConditionsItemField $field, FilterConditionsItemOperator $operator, $value, bool $not, FilterConditionsItemCombinator $combinator, bool $enabled) {
		$this->field = $field;
		$this->operator = $operator;
		$this->value = $value;
		$this->not = $not;
		$this->combinator = $combinator;
		$this->enabled = $enabled;
	}

	public function getField(): FilterConditionsItemField {
		return $this->field;
	}

	public function getOperator(): FilterConditionsItemOperator {
		return $this->operator;
	}

	public function getValue() {
		return $this->value;
	}

	public function getNot(): bool {
		return $this->not;
	}

	public function getCombinator(): FilterConditionsItemCombinator {
		return $this->combinator;
	}

	public function getEnabled(): bool {
		return $this->enabled;
	}

	public function withField(FilterConditionsItemField $field): self {
		$clone = clone $this;
		$clone->field = $field;

		return $clone;
	}

	public function withOperator(FilterConditionsItemOperator $operator): self {
		$clone = clone $this;
		$clone->operator = $operator;

		return $clone;
	}

	public function withValue($value): self {
		$validator = new \JsonSchema\Validator();
		$validator->validate($value, self::$schema['properties']['value']);
		if (!$validator->isValid()) {
			throw new \InvalidArgumentException($validator->getErrors()[0]['message']);
		} $clone = clone $this;
		$clone->value = $value;

		return $clone;
	}

	public function withNot(bool $not): self {
		$validator = new \JsonSchema\Validator();
		$validator->validate($not, self::$schema['properties']['not']);
		if (!$validator->isValid()) {
			throw new \InvalidArgumentException($validator->getErrors()[0]['message']);
		} $clone = clone $this;
		$clone->not = $not;

		return $clone;
	}

	public function withCombinator(FilterConditionsItemCombinator $combinator): self {
		$clone = clone $this;
		$clone->combinator = $combinator;

		return $clone;
	}

	public function withEnabled(bool $enabled): self {
		$validator = new \JsonSchema\Validator();
		$validator->validate($enabled, self::$schema['properties']['enabled']);
		if (!$validator->isValid()) {
			throw new \InvalidArgumentException($validator->getErrors()[0]['message']);
		} $clone = clone $this;
		$clone->enabled = $enabled;

		return $clone;
	}

	public static function buildFromInput(array|object $input, bool $validate = true): FilterConditionsItem {
		$input = is_array($input) ? \JsonSchema\Validator::arrayToObjectRecursive($input) : $input;
		if ($validate) {
			static::validateInput($input);
		} $field = FilterConditionsItemField::buildFromInput($input->{'field'}, validate: $validate);
		$operator = FilterConditionsItemOperator::from($input->{'operator'});
		$value = $input->{'value'};
		$not = (bool) $input->{'not'};
		$combinator = FilterConditionsItemCombinator::from($input->{'combinator'});
		$enabled = (bool) $input->{'enabled'};
		$obj = new self($field, $operator, $value, $not, $combinator, $enabled);

		return $obj;
	}

	public function toJson(): array {
		$output = [];
		$output['field'] = $this->field->toJson();
		$output['operator'] = $this->operator->value;
		$output['value'] = $this->value;
		$output['not'] = $this->not;
		$output['combinator'] = $this->combinator->value;
		$output['enabled'] = $this->enabled;

		return $output;
	}

	public static function validateInput(array|object $input, bool $return = false): bool {
		$validator = new \JsonSchema\Validator();
		$input = is_array($input) ? \JsonSchema\Validator::arrayToObjectRecursive($input) : $input;
		$validator->validate($input, self::$schema);
		if (!$validator->isValid() && !$return) {
			$errors = array_map(function (array $e): string { return $e['property'].': '.$e['message']; }, $validator->getErrors());
			throw new \InvalidArgumentException(join(', ', $errors));
		}

return $validator->isValid();
	}

	public function __clone() {
		$this->field = clone $this->field;
	}
}
