<?php

namespace KupShop\GraphQLBundle\ApiPos\Controller;

use KupShop\ContentBundle\View\Exception\ValidationException;
use KupShop\GraphQLBundle\ApiPos\Types\Collection\PosOrderPaymentsCollection;
use KupShop\GraphQLBundle\ApiPos\Types\Collection\PosPaymentCollection;
use KupShop\GraphQLBundle\ApiPos\Types\Payments\PosConfirmPayment;
use KupShop\GraphQLBundle\ApiPos\Types\Payments\PosPaymentsStatusUpdate;
use KupShop\KupShopBundle\Context\PosContext;
use KupShop\POSBundle\Event\PosPaymentEvent;
use KupShop\POSBundle\Util\PosPaymentUtil;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use TheCodingMachine\GraphQLite\Annotations\Mutation;
use TheCodingMachine\GraphQLite\Annotations\Query;
use TheCodingMachine\GraphQLite\Annotations\UseInputType;

class PosPaymentController
{
    public function __construct(
        protected ?PosPaymentUtil $paymentUtil,
        protected LoggerInterface $logger,
        protected EventDispatcherInterface $eventDispatcher,
        protected PosContext $posContext,
    ) {
    }

    #[Mutation]
    public function posMakeSelection(string $price, string $note = ''): int
    {
        $posEntity = $this->posContext->getActive();
        $response = $this->paymentUtil->createNonOrderPayment($posEntity->getId(), toDecimal($price)->mul(toDecimal(-1))->asString(), $note, \Payment::METHOD_CASH_SELECTION);

        $this->logger->notice('POS API: posMakeSelection', ['data' => [
            'requestParams' => serialize([
                'idPos' => $posEntity->getId(),
                'price' => $price,
                'note' => $note,
                'method' => \Payment::METHOD_CASH_SELECTION,
            ]),
            'response' => serialize($response),
        ]]);

        $this->eventDispatcher->dispatch(
            new PosPaymentEvent($posEntity, $price, \Payment::METHOD_CASH_SELECTION, null, $note),
            PosPaymentEvent::POS_SELECT_PAYMENT
        );

        return $response;
    }

    #[Mutation]
    public function posMakeInsertion(string $price, string $note = ''): int
    {
        $posEntity = $this->posContext->getActive();
        $response = $this->paymentUtil->createNonOrderPayment($posEntity->getId(), $price, $note, \Payment::METHOD_CASH_INSERTION);

        $this->logger->notice('POS API: posMakeInsertion', ['data' => [
            'requestParams' => serialize([
                'idPos' => $posEntity->getId(),
                'price' => $price,
                'note' => $note,
                'method' => \Payment::METHOD_CASH_INSERTION,
            ]),
            'response' => serialize($response),
        ]]);

        $this->eventDispatcher->dispatch(
            new PosPaymentEvent($posEntity, $price, \Payment::METHOD_CASH_INSERTION, null, $note),
            PosPaymentEvent::POS_INSERT_PAYMENT
        );

        return $response;
    }

    #[Query]
    public function posPaymentList(int $pageDivide = 10, int $page = 1, ?string $method = null): PosPaymentCollection
    {
        return $this->paymentUtil->getPosPaymentList($this->posContext->getActiveId(), $pageDivide, $page, $method);
    }

    #[Query]
    public function orderPayments(int $idOrder): PosOrderPaymentsCollection
    {
        return $this->paymentUtil->getOrderPayments($idOrder);
    }

    #[Mutation]
    public function updateOrderPayments(int $idOrder, #[UseInputType('[PosPaymentStatusInput!]!')] array $payments): PosPaymentsStatusUpdate
    {
        try {
            return $this->paymentUtil->setPaymentStatus($idOrder, $payments);
        } catch (\Exception $e) {
            return new PosPaymentsStatusUpdate(isPaid: false, remainingPayment: 0, posOrderPayments: new PosOrderPaymentsCollection([]), exception: $e->getMessage());
        }
    }

    #[Mutation]
    public function confirmPayment(int $idOrder, string $uuidPayment, string $paidPrice, string $methodPayment, ?string $terminal = null): PosConfirmPayment
    {
        try {
            $response = $this->paymentUtil->confirmPayment($idOrder, $uuidPayment, $paidPrice, $methodPayment, $terminal);
        } catch (ValidationException|\Exception $e) {
            $response = new PosConfirmPayment(null, false, $e->getMessage());
        }

        $this->logger->notice('POS API: confirmPayment', ['data' => [
            'requestParams' => serialize([
                'posId' => $this->posContext->getActiveId(),
                'idOrder' => $idOrder,
                'uuidPayment' => $uuidPayment,
                'paidPrice' => $paidPrice,
                'methodPayment' => $methodPayment,
                'terminal' => $terminal,
            ]),
            'response' => serialize($response),
        ]]);

        return $response;
    }
}
