<?php

declare(strict_types=1);

namespace ShopManagerPro\Products\DTO\Generated;

class Product {
	private static array $schema = ['type' => 'object', 'required' => ['acf', 'basic', 'customMeta', 'defaultTaxonomy', 'productAttribute'], 'additionalProperties' => false, 'properties' => ['acf' => ['type' => 'object', 'additionalProperties' => ['anyOf' => [['type' => 'string'], ['type' => 'number'], ['type' => 'boolean'], ['type' => 'null'], ['type' => 'array', 'items' => ['type' => 'string']]]]], 'basic' => ['type' => 'object', 'required' => ['id', 'parentId', 'name', 'descriptionLong', 'descriptionShort', 'imageId', 'galleryImageIds', 'postStatus', 'sku', 'regularPrice', 'salePrice', 'stock', 'stockStatus', 'taxClass', 'taxStatus', 'totalSales'], 'properties' => ['id' => ['type' => 'integer'], 'parentId' => ['type' => 'integer'], 'name' => ['type' => 'string'], 'descriptionLong' => ['type' => 'string'], 'descriptionShort' => ['type' => 'string'], 'imageId' => ['oneOf' => [['type' => 'integer'], ['type' => 'null']]], 'galleryImageIds' => ['type' => 'array', 'items' => ['type' => 'integer']], 'postStatus' => ['type' => 'string', 'enum' => ['draft', 'pending', 'private', 'publish', 'trash']], 'sku' => ['type' => 'string'], 'regularPrice' => ['oneOf' => [['type' => 'number'], ['type' => 'null']]], 'salePrice' => ['oneOf' => [['type' => 'number'], ['type' => 'null']]], 'stock' => ['oneOf' => [['type' => 'integer'], ['type' => 'null']]], 'stockStatus' => ['oneOf' => [['type' => 'string', 'enum' => ['instock', 'onbackorder', 'outofstock']], ['type' => 'null']]], 'taxClass' => ['oneOf' => [['type' => 'string'], ['type' => 'null']]], 'taxStatus' => ['oneOf' => [['type' => 'string', 'enum' => ['none', 'shipping', 'taxable']], ['type' => 'null']]], 'totalSales' => ['type' => 'integer']]], 'customMeta' => ['type' => 'object', 'additionalProperties' => ['type' => ['string', 'number', 'integer']]], 'defaultTaxonomy' => ['type' => 'object', 'additionalProperties' => ['type' => 'array', 'items' => ['type' => 'integer']]], 'productAttribute' => ['type' => 'object', 'additionalProperties' => ['type' => 'array', 'items' => ['type' => 'integer']]]]];
	private array $acf;
	private ProductBasic $basic;
	private array $customMeta;
	private array $defaultTaxonomy;
	private array $productAttribute;

	public function __construct(array $acf, ProductBasic $basic, array $customMeta, array $defaultTaxonomy, array $productAttribute) {
		$this->acf = $acf;
		$this->basic = $basic;
		$this->customMeta = $customMeta;
		$this->defaultTaxonomy = $defaultTaxonomy;
		$this->productAttribute = $productAttribute;
	}

	public function getAcf(): array {
		return $this->acf;
	}

	public function getBasic(): ProductBasic {
		return $this->basic;
	}

	public function getCustomMeta(): array {
		return $this->customMeta;
	}

	public function getDefaultTaxonomy(): array {
		return $this->defaultTaxonomy;
	}

	public function getProductAttribute(): array {
		return $this->productAttribute;
	}

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

		return $clone;
	}

	public function withBasic(ProductBasic $basic): self {
		$clone = clone $this;
		$clone->basic = $basic;

		return $clone;
	}

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

		return $clone;
	}

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

		return $clone;
	}

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

		return $clone;
	}

	public static function buildFromInput(array|object $input, bool $validate = true): Product {
		$input = is_array($input) ? \JsonSchema\Validator::arrayToObjectRecursive($input) : $input;
		if ($validate) {
			static::validateInput($input);
		} $acf = (array) $input->{'acf'};
		$basic = ProductBasic::buildFromInput($input->{'basic'}, validate: $validate);
		$customMeta = (array) $input->{'customMeta'};
		$defaultTaxonomy = (array) $input->{'defaultTaxonomy'};
		$productAttribute = (array) $input->{'productAttribute'};
		$obj = new self($acf, $basic, $customMeta, $defaultTaxonomy, $productAttribute);

		return $obj;
	}

	public function toJson(): array {
		$output = [];
		$output['acf'] = $this->acf;
		$output['basic'] = $this->basic->toJson();
		$output['customMeta'] = $this->customMeta;
		$output['defaultTaxonomy'] = $this->defaultTaxonomy;
		$output['productAttribute'] = $this->productAttribute;

		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->basic = clone $this->basic;
	}
}
