<?php

declare(strict_types=1);

namespace External\PompoBundle\Resources\script;

use KupShop\AdminBundle\Util\Script\Script;
use KupShop\BonusProgramBundle\Utils\PointEvaluator;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\OrderingBundle\Entity\Order\OrderItem;
use Query\Operator;

class PompoGenerateMissingBonusPointsScript extends Script
{
    protected static $name = '[pompo] Dogenerovat chybejici body k prodejkam';
    protected static $defaultParameters = [
        'dryRun' => true,
    ];

    protected function run(array $arguments)
    {
        $qb = sqlQueryBuilder()
            ->select('o.id')
            ->from('orders', 'o')
            ->leftJoin('o', 'bonus_points', 'bp', 'bp.id_order = o.id')
            ->andWhere('o.status_storno = 0')
            ->andWhere('o.id_user IS NOT NULL')
            ->andWhere('bp.id IS NULL')
            ->andWhere('o.date_created >= "2023-09-01 00:00:00"');

        if (empty($arguments['ALL_ORDERS'])) {
            // pouze prodejky
            $qb->andWhere(Operator::findInSet(['NP'], 'o.flags'));
            $note = 'Body za nákup na prodejně';
        } else {
            $note = translate_shop('note_order_points_added', 'bonus_program');
        }

        $pointEvaluator = ServiceContainer::getService(PointEvaluator::class);

        $count = 0;
        foreach ($qb->execute() as $row) {
            $order = \Order::get($row['id']);

            $points = \DecimalConstants::zero();

            /** @var OrderItem $item */
            foreach ($order->fetchItems() as $item) {
                if (!$item->getProductId()) {
                    continue;
                }

                $data = $item->getNote();
                $isDiscounted = false;
                if (!empty($data['totalDiscount'])) {
                    $isDiscounted = true;
                }

                $pointEvaluator->setPrice($item->getTotalPrice()->getPriceWithVat());

                $itemPoints = $pointEvaluator->evaluatePoints(null);
                // pokud je to nezlevneny lego produkt, tak davam 5 nasobek bodu
                if ($this->isLegoProduct($item->getProductId()) && !$isDiscounted) {
                    $itemPoints = $itemPoints->mul(toDecimal(5));
                }

                $points = $points->add($itemPoints);
            }

            if ($points->isPositive()) {
                $count++;
                $this->log('['.$order->date_created->format('d.m.Y H:i:s').'] '.$order->order_no.': '.$points->asFloat());
                if ($arguments['dryRun']) {
                    continue;
                }

                sqlQueryBuilder()
                    ->insert('bonus_points')
                    ->directValues(
                        [
                            'id_user' => $order->id_user,
                            'points' => $points,
                            'date_created' => (new \DateTime())->format('Y-m-d H:i:s'),
                            'note' => sprintf($note, $order->order_no),
                            'status' => 'active',
                            'id_order' => $order->id,
                        ]
                    )->execute();

                $order->logHistory(sprintf('Za tuto objednávku bylo na účet uživatele přičteno %s bodů', $points->asFloat()));
            }
        }

        $this->log("Celkem {$count} objednávek.");
    }

    private function isLegoProduct(int $productId): bool
    {
        $producer = sqlQueryBuilder()
            ->select('pr.name')
            ->from('products', 'p')
            ->join('p', 'producers', 'pr', 'pr.id = p.producer')
            ->where(Operator::equals(['p.id' => $productId]))
            ->execute()->fetchOne();

        if ($producer) {
            if (strpos(mb_strtolower($producer), 'lego') !== false) {
                return true;
            }
        }

        return false;
    }
}

return PompoGenerateMissingBonusPointsScript::class;
