<?php

namespace Myvetshop\Module\Clinique\Accounting\Export\Exporter;

use Myvetshop\Module\Clinique\Accounting\Export\Exporter\PostProcess\ExportPostProcessorInterface;
use Myvetshop\Module\Clinique\Accounting\Export\Exporter\Provider\LineProviderInterface;
use Myvetshop\Module\Clinique\Accounting\Export\Model\ExportLine;
use Myvetshop\Module\Clinique\Accounting\Export\Model\SimpleAccountingLineInterface;
use Myvetshop\Module\Clinique\Accounting\Export\Repository\OrderPaymentRepository;

/**
 * @template DocType of \OrderInvoice|\OrderSlip
 *
 * @implements DocumentExporterInterface<DocType>
 */
abstract class AbstractDocumentExporter implements DocumentExporterInterface
{
    protected OrderPaymentRepository $orderPaymentRepository;

    /**
     * @var list<LineProviderInterface<DocType>>
     */
    protected array $providers;

    /**
     * @var ExportPostProcessorInterface[]
     */
    protected array $postProcessors;

    protected string $entitled;

    /**
     * @param DocType $document
     * @param DocType $document
     */
    abstract protected function getDocumentDate($document): \DateTimeImmutable;

    /**
     * @param DocType $document
     */
    abstract protected function getDocumentReference($document, \Order $order): string;

    protected function getPaymentMethod(\Order $order): string
    {
        $orderPayments = $this->orderPaymentRepository->getByOrder($order);

        if (!empty($orderPayments)) {
            return $orderPayments[0]->payment_method;
        }

        return '';
    }

    /**
     * @param DocType $document
     */
    public function export($document, \Order $order): array
    {
        $documentDate = $this->getDocumentDate($document);
        $documentReference = $this->getDocumentReference($document, $order);
        $paymentMethod = $this->getPaymentMethod($order);

        /**
         * @var list<SimpleAccountingLineInterface> $simpleLines
         */
        $simpleLines = \call_user_func_array(
            'array_merge',
            \array_map(
                fn ($provider) => $provider->getAccountingLines($document, $order),
                $this->providers
            )
        );

        $lines = \array_map(
            fn (SimpleAccountingLineInterface $line) => ExportLine::createFromSimpleLine(
                $line,
                $documentDate,
                $documentReference,
                $this->entitled,
                $paymentMethod,
            ),
            $simpleLines
        );

        foreach ($this->postProcessors as $processor) {
            $lines = $processor->postProcess($lines);
        }

        return $lines;
    }

    public function addPostProcessor(ExportPostProcessorInterface $postProcessor): void
    {
        if (!\in_array($postProcessor, $this->postProcessors, true)) {
            $this->postProcessors[] = $postProcessor;
        }
    }

    public function removePostProcessor(ExportPostProcessorInterface $postProcessor): void
    {
        if (\in_array($postProcessor, $this->postProcessors, true)) {
            $this->postProcessors = \array_values(
                \array_filter(
                    $this->postProcessors,
                    fn ($processor) => $processor !== $postProcessor,
                )
            );
        }
    }
}
