<?php

namespace KupShop\AutopilotBundle\Util;

use KupShop\KupShopBundle\Config;
use Query\Operator;
use Query\Order;

class AutopilotUtil
{
    protected $testMode = false;
    protected $testLog = [];
    protected $fromStatuses = [];

    public function setFromStatuses($fromStatuses)
    {
        $this->fromStatuses = $fromStatuses;
    }

    public function getFromStatuses()
    {
        if (empty($this->fromStatuses)) {
            $dbFromStatuses = \Settings::getDefault()['autopilot']['from_statuses'] ?? null;
            $this->setFromStatuses(empty($dbFromStatuses) ? getStatuses('active') : $dbFromStatuses);
        }

        return $this->fromStatuses;
    }

    public function getTestMode()
    {
        return $this->testMode;
    }

    public function setTestMode($test)
    {
        $this->testMode = $test;

        return $this;
    }

    public function getTestLog()
    {
        return $this->testLog;
    }

    public function getAutopilotDescription()
    {
        $statuses = Config::get()['Order']['Status']['global'];
        $active = array_flip($this->getFromStatuses());
        $active = array_intersect_key($statuses, $active);

        return [
            'ještě nevyřízené ('.implode(', ', $active).'),',
            'kompletní (vše je skladem),',
            'jsou zaplacené nebo na dobírku,',
            'mají vyřešené poznámky,',
        ];
    }

    protected function getBaseQueryBuilder()
    {
        return sqlQueryBuilder()
            ->from('orders', 'o')
            ->leftJoin('o', 'order_items', 'oi', 'oi.id_order=o.id')
            ->leftJoin('oi', 'products', 'p', 'oi.id_product=p.id')
            ->leftjoin('oi', 'products_variations', 'pv', 'pv.id=oi.id_variation')
            ->andWhere("NOT COALESCE(JSON_CONTAINS(oi.note, '\"return\"', '$.item_type'), FALSE)")
            ->groupBy('o.id');
    }

    protected function getOrderCountQueryBuilder()
    {
        return sqlQueryBuilder()->select('SUM(oi2.pieces)')
            ->from('order_items', 'oi2')
            ->leftJoin('oi2', 'orders', 'o2', 'oi2.id_order=o2.id')
            ->where('oi2.id_product=p.id AND o2.date_created >= o.date_created AND o2.status_storno=0 AND ((oi2.id_variation IS NULL AND oi.id_variation IS NULL) OR oi.id_variation=oi2.id_variation)')
            ->andWhere(Operator::inIntArray($this->getFromStatuses(), 'o2.status'))
            ->andWhere("NOT COALESCE(JSON_CONTAINS(oi2.note, '\"return\"', '$.item_type'), FALSE)");
    }

    protected function getOrderQueryBuilder()
    {
        $orderCount = $this->getOrderCountQueryBuilder();

        return $this->getBaseQueryBuilder()
            ->select('o.id, o.status, 
            MIN(COALESCE(pv.in_store, p.in_store) - oi.pieces + ('.$orderCount->getSQL().')) as min_in_store')
            ->andWhere('o.status_storno=0')
            ->andWhere(Operator::inIntArray($this->getFromStatuses(), 'o.status'))
            ->andWhere('o.total_price > 0')
            ->andWhere(Operator::not(Operator::findInSet(['R'], 'o.flags')))
            ->andWhere(Operator::orX('o.status_payed = 1', Order::byPaymentMethods(['METHOD_COD'])))
            ->having('min_in_store >= 0')
            ->addParameters($orderCount->getParameters(), $orderCount->getParameterTypes());
    }

    // zakladni autopilot prepina objednavky ve stavu "active" do stavu "autopilotStatus", pokud zbozi je skladem
    public function autopilot($autopilotStatus = null)
    {
        $autopilotStatus = (isset($autopilotStatus) ? $autopilotStatus : (\Settings::getDefault()['autopilot']['status'] ?? null));
        if (!isset($autopilotStatus)) {
            return;
        }

        foreach ($this->getOrderQueryBuilder()->execute() as $row) {
            $order = new \Order($row['id']);
            $order->createFromDB($row['id']);

            $this->processOrder($order, $autopilotStatus);
        }
    }

    protected function processOrder(\Order $order, $autopilotStatus)
    {
        // prepnout do stavu "autopilotStatus", pridat comment a flag, neposilat email
        $this->changeStatus($order, $autopilotStatus);
        $this->addFlag($order);
    }

    protected function changeStatus(\Order $order, $autopilotStatus)
    {
        $comment = translate('autopilotMessage', 'autopilotTab', false, true);
        if ($this->getTestMode()) {
            $orderStatus = Config::get()['Order']['Status']['global'][$order->status] ?? '';
            $status = Config::get()['Order']['Status']['global'][$autopilotStatus] ?? '';
            $this->testLog[$order->id][] = "Změna stavu z '{$orderStatus}' na '{$status}'";
            $this->testLog[$order->id][] = "Komentář '{$comment}' (bez odeslání e-mailu zákazníkovi)";

            return;
        }

        $order->changeStatus($autopilotStatus, $comment, false);
    }

    protected function addFlag(\Order $order)
    {
        if ($this->getTestMode()) {
            $flag = Config::get()['Order']['Flags']['ZA']['name'] ?? '';
            $this->testLog[$order->id][] = "Příznak 'ZA' - ".$flag;

            return;
        }

        $order->addFlag('ZA');
    }
}
