<?php

namespace common\logic\Order\Order\Service;

use common\components\TillerClient;
use common\helpers\MeanPayment;
use common\logic\AbstractManager;
use common\logic\Order\Order\Model\Order;
use common\logic\Order\ProductOrder\Service\ProductOrderSolver;
use common\logic\Producer\Producer\Service\ProducerSolver;

class TillerManager extends AbstractManager
{
    protected ?bool $tillerActivated;
    protected ProducerSolver $producerSolver;
    protected TillerClient $tillerClient;
    protected OrderSolver $orderSolver;
    protected OrderBuilder $orderBuilder;
    protected ProductOrderSolver $productOrderSolver;

    public function loadDependencies(): void
    {
        $this->producerSolver = $this->loadService(ProducerSolver::class);
        if($this->producerSolver->getProducerContext(false)) {
            $this->tillerActivated = $this->producerSolver->getConfig('tiller');
            $this->tillerClient = $this->getClient();
        }
        $this->orderSolver = $this->loadService(OrderSolver::class);
        $this->orderBuilder = $this->loadService(OrderBuilder::class);
        $this->productOrderSolver = $this->loadService(ProductOrderSolver::class);
    }

    public function getClient(): TillerClient
    {
        return new TillerClient(
            $this->producerSolver->getConfig('tiller_provider_token'),
            $this->producerSolver->getConfig('tiller_restaurant_token')
        );
    }

    public function synchronizeDistribution(string $date): array
    {
        $return = [];

        if($this->tillerActivated) {
            $isSynchro = $this->isSynchronized($date);

            if (!$isSynchro) {
                $orders = Order::searchAll([
                    'distribution.date' => $date,
                    'order.tiller_synchronization' => 1
                ], [
                    'conditions' => 'date_delete IS NULL'
                ]);

                $strDate = date('Y-m-d\T12:i:s+0000', strtotime($date) + 1);

                if ($orders && count($orders)) {
                    foreach ($orders as $order) {
                        $this->orderBuilder->initOrder($order);
                        $lines = [];
                        foreach ($order->productOrder as $productOrder) {
                            $lines[] = [
                                'name' => $productOrder->product->name,
                                'price' => $this->productOrderSolver->getPriceWithTax($productOrder) * 100 * $productOrder->quantity,
                                'tax' => $productOrder->taxRate->value * 100,
                                'date' => $strDate,
                                'quantity' => $productOrder->quantity
                            ];
                        }

                        $typePaymentTiller = '';
                        if ($order->mean_payment == MeanPayment::MONEY) {
                            $typePaymentTiller = 'CASH';
                        }
                        if ($order->mean_payment == MeanPayment::CREDIT_CARD
                            || $order->mean_payment == MeanPayment::CREDIT
                            || $order->mean_payment == MeanPayment::TRANSFER
                            || $order->mean_payment == MeanPayment::OTHER) {
                            $typePaymentTiller = 'CARD';
                        }
                        if ($order->mean_payment == MeanPayment::CHEQUE) {
                            $typePaymentTiller = 'BANK_CHECK';
                        }
                        if (!strlen($typePaymentTiller) || !$order->mean_payment) {
                            $typePaymentTiller = 'CASH';
                        }

                        if (!$this->isSynchronized($date, $order->id)) {
                            $returnTiller = $this->tillerClient->postOrder([
                                'externalId' => $order->id,
                                'type' => 1,
                                'status' => 'IN_PROGRESS',
                                'openDate' => $strDate,
                                'closeDate' => $strDate,
                                'lines' => $lines,
                                'payments' => [
                                    [
                                        'type' => $typePaymentTiller,
                                        'amount' => $this->orderSolver->getOrderAmountWithTax(
                                                $order,
                                                Order::AMOUNT_PAID
                                            ) * 100,
                                        'status' => 'ACCEPTED',
                                        'date' => $strDate
                                    ]
                                ]
                            ]);

                            $returnTillerObject = json_decode($returnTiller);
                            $order->tiller_external_id = '' . $returnTillerObject->id;
                            $order->save();

                            $return[] = $returnTiller;
                        }
                    }
                }
            }
        }

        return $return;
    }

    public function isSynchronized($date, $idOrder = null): bool
    {
        if ($this->tillerActivated) {
            $ordersTiller = $this->tillerClient->getOrders($date);

            $ordersOpendistrib = Order::searchAll([
                'distribution.date' => $date,
                'order.tiller_synchronization' => 1
            ], [
                'conditions' => 'date_delete IS NULL'
            ]);

            $ordersOpendistribSynchro = [];

            if ($ordersOpendistrib) {
                foreach ($ordersOpendistrib as $orderOpendistrib) {
                    $this->orderBuilder->initOrder($orderOpendistrib);
                    $ordersOpendistribSynchro[$orderOpendistrib->id] = false;
                    if (isset($ordersTiller->orders)) {
                        foreach ($ordersTiller->orders as $orderTiller) {
                            if ($orderOpendistrib->tiller_external_id == $orderTiller->id) {
                                $amountTotalPaidOrderOpendistrib = (int)round(
                                    $this->orderSolver->getOrderAmountWithTax($orderOpendistrib, Order::AMOUNT_PAID) * 100
                                );
                                if ($amountTotalPaidOrderOpendistrib >= (int)$orderTiller->currentPayedAmount
                                    || $amountTotalPaidOrderOpendistrib >= (int)$orderTiller->currentBill) {
                                    $ordersOpendistribSynchro[$orderOpendistrib->id] = true;
                                }
                            }
                        }
                    }
                }
            }

            if($idOrder && isset($ordersOpendistribSynchro[$idOrder])) {
                return $ordersOpendistribSynchro[$idOrder];
            }
            else {
                foreach ($ordersOpendistribSynchro as $idOrder => $isSynchro) {
                    if (!$isSynchro) {
                        return false;
                    }
                }
            }

            return true;
        }

        return false;
    }
}