<?php 
 
namespace App\Service\App\Merchant\FecReport\Listener; 
 
use App\Background\Data\AddFecEntryData; 
use App\Core\BackgroundWork\Contract\IClient; 
use App\Core\MerchantSelector\Contract\IMerchantSelector; 
use App\Service\App\Merchant\CustomFeature\Implementation\FecReportCustomFeature; 
use App\Service\App\Merchant\Invoice\Event\FinalizeInvoiceEvent; 
use App\Service\App\Merchant\Invoice\Event\PaidInvoiceEvent; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
 
class InvoiceListener implements EventSubscriberInterface 
{ 
 
    /** 
     * Client 
     * 
     * @var IClient 
     */ 
    private IClient $client; 
 
    /** 
     * Merchant selector 
     * 
     * @var IMerchantSelector 
     */ 
    private IMerchantSelector $merchantSelector; 
 
    /** 
     * FEC report custom feature 
     * 
     * @var FecReportCustomFeature 
     */ 
    private FecReportCustomFeature $fecReportCustomFeature; 
 
    /** 
     * Constructor 
     * 
     * @param IClient $client 
     * @param IMerchantSelector $merchantSelector 
     * @param FecReportCustomFeature $fecReportCustomFeature 
     */ 
    public function __construct( 
        IClient $client, 
        IMerchantSelector $merchantSelector, 
        FecReportCustomFeature $fecReportCustomFeature 
    ) 
    { 
        $this->client = $client; 
        $this->merchantSelector = $merchantSelector; 
        $this->fecReportCustomFeature = $fecReportCustomFeature; 
    } 
 
    /** 
     * Returns an array of event names this subscriber wants to listen to. 
     * 
     * The array keys are event names and the value can be: 
     * 
     *  * The method name to call (priority defaults to 0) 
     *  * An array composed of the method name to call and the priority 
     *  * An array of arrays composed of the method names to call and respective 
     *    priorities, or 0 if unset 
     * 
     * For instance: 
     * 
     *  * ['eventName' => 'methodName'] 
     *  * ['eventName' => ['methodName', $priority]] 
     *  * ['eventName' => [['methodName1', $priority], ['methodName2']]] 
     * 
     * The code must not depend on runtime state as it will only be called at compile time. 
     * All logic depending on runtime state must be put into the individual methods handling the events. 
     * 
     * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>> 
     */ 
    public static function getSubscribedEvents() 
    { 
        return [ 
            FinalizeInvoiceEvent::NAME => 'onFinalizeInvoice', 
            PaidInvoiceEvent::NAME => 'onPaidInvoice', 
        ]; 
    } 
 
    /** 
     * On finalize invoice 
     * 
     * @param FinalizeInvoiceEvent $event 
     * @return void 
     */ 
    public function onFinalizeInvoice(FinalizeInvoiceEvent $event): void 
    { 
        if (!$this->fecReportCustomFeature->isEnabled()) { 
            return; 
        } 
 
        // if invoice is paid just skip it, as we will run task in onPaidInvoice 
        if ($event->isPaid()) { 
            return; 
        } 
 
        $this->client->runJob(new AddFecEntryData($this->merchantSelector->getMerchant(), $event->getInvoiceId())); 
    } 
 
    /** 
     * On paid invoice event 
     * 
     * @param PaidInvoiceEvent $event 
     * @return void 
     */ 
    public function onPaidInvoice(PaidInvoiceEvent $event): void 
    { 
        if (!$this->fecReportCustomFeature->isEnabled()) { 
            return; 
        } 
 
        $this->client->runJob(new AddFecEntryData($this->merchantSelector->getMerchant(), $event->getInvoiceId())); 
    } 
 
}