<?php

declare(strict_types=1);

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Commerce\Catalog\Outbox;

final readonly class CatalogMutationContext
{
    /**
     * @param array<string, array{0: mixed, 1: mixed}> $changeSet
     */
    private function __construct(
        private array $changeSet,
        private bool $insertion,
        private bool $deletion,
        private bool $productRemoval,
    ) {}

    /**
     * @param array<string, array{0: mixed, 1: mixed}> $changeSet
     */
    public static function insertion(array $changeSet): self
    {
        return new self($changeSet, true, false, false);
    }

    /**
     * @param array<string, array{0: mixed, 1: mixed}> $changeSet
     */
    public static function update(array $changeSet, bool $productRemoval = false): self
    {
        return new self($changeSet, false, false, $productRemoval);
    }

    public static function deletion(bool $productRemoval = false): self
    {
        return new self([], false, true, $productRemoval);
    }

    public static function unspecified(): self
    {
        return new self([], false, false, false);
    }

    public function isInsertion(): bool
    {
        return $this->insertion;
    }

    public function isDeletion(): bool
    {
        return $this->deletion;
    }

    public function isProductRemoval(): bool
    {
        return $this->productRemoval;
    }

    public function isUnspecified(): bool
    {
        return !$this->insertion && !$this->deletion && [] === $this->changeSet;
    }

    /**
     * @param list<string> $fields
     */
    public function changesAny(array $fields): bool
    {
        foreach ($fields as $field) {
            if (array_key_exists($field, $this->changeSet)) {
                return true;
            }
        }

        return false;
    }

    public function oldValue(string $field): mixed
    {
        return $this->changeSet[$field][0] ?? null;
    }
}
