<?php

use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\AdminList\FiltersStorage;

class InventoryList extends BaseList
{
    use FiltersStorage;

    protected $tableDef = [
        'id' => 's.id',
        'fields' => [
            'ID' => ['field' => 's.id'],
            'Pozice ve skladu' => ['field' => 's.name'],
            'Hotovo' => ['field' => 'finished', 'render' => 'renderBoolean', 'size' => 0.5],
            'Poznámka' => ['field' => 's.note', 'size' => 2],
            'Datum aplikace' => ['field' => 'date_apply', 'render' => 'renderDatetime', 'size' => 0.5],
        ],
    ];

    public function getQuery()
    {
        $qb = sqlQueryBuilder()
                    ->select('s.id', 's.ID', 's.name', 'IF(s.finished,"Y","N") as finished', 's.note', 's.date_apply')
                    ->from('inventory', 's');

        extract($_GET, EXTR_SKIP | EXTR_REFS);

        // ###########
        if (!empty($IDs)) {
            $qb->andWhere(\Query\Operator::equals(['s.id' => $IDs, 's.name' => $IDs], 'OR'));
        }
        // ###########
        if (!empty($IDpv)) {
            list($IDp, $IDv) = explode(':', $IDpv);
        }
        // ###########
        if (!empty($IDp)) {
            $qb->leftJoin('s', 'inventory_items', 'si', 'si.id_inventory=s.id')
                ->leftJoin('si', 'products', 'p', 'si.id_product=p.id')
                ->leftJoin('p', 'vats', 'v', 'p.vat=v.id');

            if (!empty($IDv)) {
                $qb->andWhere(\Query\Operator::equals(['si.id_variation' => $IDv]));
            }

            $qb->andWhere(\Query\Operator::equals(['si.id_product' => $IDp]));
        }
        // ###########
        if (!empty($name)) {
            $qb->andWhere(\Query\Operator::equals(['s.name' => $name]));
        }

        return $qb;
    }

    public function handleCleanProducts()
    {
        sqlQuery('TRUNCATE TABLE inventory_items');

        $this->returnOK('Produkty na všech pozicích byly smazány');
    }

    public function handleCleanAll()
    {
        sqlQuery('DELETE FROM inventory');

        $this->returnOK('Všechny pozice byly odstraněny');
    }

    public function handleApplyToProducts()
    {
        $changeCount = 0;

        sqlQuery('DROP TABLE IF EXISTS tmp_inventory');

        sqlQuery("CREATE TABLE tmp_inventory
           SELECT p.id id_product, pv.id id_variation, COALESCE(SUM(ii.quantity),0) quantity, GROUP_CONCAT(DISTINCT i.name ORDER BY i.name SEPARATOR ',') position
           FROM products p
           LEFT JOIN products_variations pv ON p.id=pv.id_product
           LEFT JOIN inventory_items ii ON ii.id_product = p.id AND ((pv.id IS NULL AND ii.id_variation IS NULL) OR (ii.id_variation = pv.id))
           LEFT JOIN inventory i ON ii.id_inventory=i.id
           GROUP BY p.id, pv.id");

        sqlQuery('ALTER TABLE tmp_inventory ADD INDEX ( `id_product` )');
        sqlQuery('ALTER TABLE tmp_inventory ADD INDEX ( `id_variation` )');

        sqlStartTransaction();

        $notPacked = ' ('.join(', ', getStatuses('notpacked')).') ';
        $pNote = '';
        $vNote = '';
        if (findModule('products', 'note')) {
            $pNote = ', p.note=COALESCE(ti.position, p.note)';
            $vNote = ', pv.note=COALESCE(ti.position, pv.note)';
        }

        $SQL = sqlQuery("UPDATE products p
         LEFT JOIN products_variations pv ON p.id=pv.id_product
        LEFT JOIN tmp_inventory ti ON ti.id_product = p.id AND ti.id_variation IS NULL
        SET p.in_store = COALESCE(ti.quantity, 0) - COALESCE((
              SELECT COALESCE(SUM(pieces), 0)
              FROM order_items oi
              LEFT JOIN orders o ON oi.id_order = o.id
              WHERE o.status IN {$notPacked} AND o.status_storno=0 AND oi.id_product = p.id AND oi.id_variation IS NULL
        ), 0){$pNote}
        WHERE pv.id IS NULL");

        $changeCount += sqlAffectedRows($SQL);

        $SQL = sqlQuery("UPDATE products p
        LEFT JOIN products_variations pv ON p.id=pv.id_product
        LEFT JOIN tmp_inventory ti ON ti.id_product = p.id AND ti.id_variation = pv.id
        SET pv.in_store = COALESCE(ti.quantity, 0) - COALESCE((
              SELECT COALESCE(SUM(pieces), 0)
              FROM order_items oi
              LEFT JOIN orders o ON oi.id_order = o.id
              WHERE o.status IN {$notPacked} AND o.status_storno=0 AND oi.id_product = p.id AND oi.id_variation = pv.id
        ), 0){$vNote}
        WHERE pv.id IS NOT NULL");

        $changeCount += sqlAffectedRows($SQL);

        Variations::recalcInStore();

        // Warehouse bundle - propagate to positions
        if (findModule(\Modules::WAREHOUSE)) {
            $wrongPositions = array_column(sqlQuery('SELECT name FROM inventory i LEFT JOIN warehouse_positions wp ON wp.code = i.name WHERE wp.id IS NULL')->fetchAll(), 'name');
            if ($wrongPositions) {
                $this->returnError('Nemůžu najít pozici ve skladu k těmto pozicím v inventuře: '.join(', ', $wrongPositions));
            }

            sqlQuery('DELETE FROM warehouse_products');

            sqlQuery('INSERT INTO warehouse_products (id_product, id_variation, id_position, pieces)
                SELECT ii.id_product, ii.id_variation, wp.id, SUM(ii.quantity)
                FROM inventory_items ii
                       LEFT JOIN inventory i ON ii.id_inventory = i.id
                       LEFT JOIN warehouse_positions wp ON wp.code = i.name
                GROUP BY ii.id_product, ii.id_variation, wp.id;');
        }

        sqlQueryBuilder()->update('inventory')->set('date_apply', 'NOW()')->execute();
        addActivityLog(\KupShop\AdminBundle\Util\ActivityLog::SEVERITY_SUCCESS, \KupShop\AdminBundle\Util\ActivityLog::TYPE_CHANGE, "Proběhla aplikace inventury. Aktualizováno {$changeCount} položek. ");

        sqlFinishTransaction();

        $ErrStr = "Byl aktualizován stav {$changeCount} položek";

        $this->returnOK($ErrStr);
    }
}
