<?php

declare(strict_types=1);

namespace KupShop\OrderingBundle\Util\Order;

use Query\Operator;
use Query\QueryBuilder;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;

class OrderActivationUtil
{
    private const TOTAL_PRICE_DIFF = 2;

    private RequestStack $requestStack;

    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    }

    public function activateFromRequest(Request $request): false|int
    {
        if ($request->get('submit')) {
            $order_no = trim((string) $request->get('order_no'));

            return $this->activateOrder($order_no, (string) $request->get('email'));
        }

        if ($request->get('submit-pos')) {
            return $this->activatePosOrder(
                (string) $request->get('order_no'),
                (float) $request->get('total_price'),
                (string) $request->get('email')
            );
        }

        return false;
    }

    public function activateOrder(string $orderNo, string $email): false|int
    {
        $orderId = $this->getOrdersQueryBuilder()
            ->andWhere(
                Operator::equals(
                    [
                        'order_no' => $orderNo,
                        'invoice_email' => $email,
                    ])
            )
            ->execute()->fetchOne();

        if (!$orderId) {
            return false;
        }

        $this->saveActiveOrder($orderId);

        return $orderId;
    }

    public function activateOrderWithSecurityCode(int $id_order, string $cf): false|int
    {
        $order = new \Order($id_order);

        if ($order->createFromDB($id_order) && ($cf == $order->getSecurityCode())) {
            $this->saveActiveOrder($id_order);

            return $id_order;
        }

        return false;
    }

    public function activatePosOrder(string $orderNo, float $totalPrice, string $email): false|int
    {
        $orderId = $this->getOrdersQueryBuilder()
            ->andWhere(Operator::equals([
                'order_no' => $orderNo,
                ...(findModule(\Modules::INVOICES) ? ['invoice_no' => $orderNo] : []),
            ], 'OR'))
            ->andWhere(
                Operator::between(
                    'total_price',
                    new \Range($totalPrice - self::TOTAL_PRICE_DIFF, $totalPrice + self::TOTAL_PRICE_DIFF)
                )
            )->execute()->fetchOne();

        if (!$orderId) {
            return false;
        }

        // update order email
        sqlQueryBuilder()
            ->update('orders')
            ->directValues(['invoice_email' => $email])
            ->where(Operator::equals(['id' => $orderId]))
            ->execute();

        $this->saveActiveOrder($orderId);

        return $orderId;
    }

    private function saveActiveOrder($orderId): void
    {
        $this->requestStack->getSession()->set('active_order', $orderId);
    }

    private function getOrdersQueryBuilder(): QueryBuilder
    {
        return sqlQueryBuilder()
            ->select('id')
            ->from('orders')
            ->andWhere(Operator::inIntArray(getStatuses('handled'), 'status'))
            ->andWhere('status_storno != 1');
    }
}
