<?php

declare(strict_types=1);

require_once __DIR__ . '/OrderProblemAvoir.php';
require_once __DIR__ . '/OrderProblemInvoice.php';
require_once __DIR__ . '/OrderProblemPayment.php';
require_once __DIR__ . '/OrderProblemSomme.php';

class OrderCorrector
{
    /**
     * @var Order
     */
    protected $order;

    /**
     * Liste des correcteurs ayant trouvé un problème sur la commande.
     *
     * @var OrderProblemInterface[]
     */
    protected $problems = [];

    public function __construct(
        Order $order
    ) {
        $this->order = $order;

        // Analyse la commande
        $this->problems = [
            new OrderProblemPayment($this->order),
            new OrderProblemSomme($this->order),
            new OrderProblemAvoir($this->order),
            new OrderProblemInvoice($this->order),
        ];

        // On garde uniquement les problèmes qui concernent la commande
        $this->problems = array_filter(
            $this->problems,
            fn (OrderProblemInterface $problem) => $problem->isProblematic()
        );
    }

    /**
     * Vérifie que la commande soit cohérente.
     *
     * @param OrderProblemInterface[]|null $errors
     */
    public function isCoherent(?array &$errors = null): bool
    {
        if ($errors) {
            foreach ($this->problems as $problem) {
                $errors += $problem->getErrors();
            }
        }

        return 0 === count($this->problems);
    }

    public function isRepairable(): bool
    {
        foreach ($this->problems as $correctorError) {
            if ($correctorError->isRepairable()) {
                return true;
            }
        }

        return false;
    }

    public function repair(): void
    {
        $repaired = false;

        foreach ($this->problems as $correctorError) {
            if ($correctorError->repair()) {
                $repaired = true;
            }
        }

        if ($repaired) {
            $this->order->save();
        }
    }

    /**
     * @return string[]
     */
    public function getProblems(): array
    {
        $errors = array_map(
            fn (OrderProblemInterface $problem) => $problem->getErrors(),
            $this->problems
        );

        return array_merge(...$errors);
    }
}
