<?php

declare(strict_types=1);

namespace KupShop\KupShopBundle\Resources\script;

use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use KupShop\AdminBundle\Util\Script\Script;
use Query\Operator;

class FixProductlistCombinations extends Script
{
    protected static $name = '[FIX] Odstranit neexistující vazby produktů a variant v ceníku';
    protected static $defaultParameters = [
        'hasBackup' => 'true',
        'id_product' => '',
    ];

    protected function run(array $arguments)
    {
        // upravit podminku
        $hasBackup = boolval($arguments['hasBackup']);
        if (!$hasBackup) {
            $this->log('Musíme mít vytvořenou zálohu databáze, jinak by mohlo dojít k nevratné ztrátě dat a to nechceme!');

            return;
        }
        // nacteni integrity_unique sloupců
        $integrity_unique = sqlQueryBuilder()
            ->select('integrity_unique')
            ->from('pricelists_products')
            ->execute()->fetchFirstColumn();

        $dataToProcess = $this->getData($arguments);
        $count = $dataToProcess->rowCount();
        $this->log("Počet kombinací v product_pricielist, které budou opraveny: {$count}");
        foreach ($dataToProcess as $item) {
            $new_integrity_unique = "{$item['id_pricelist']}-{$item['correct_id_product']}-{$item['id_variation']}";
            if ($this->integrityUniqueCheck($integrity_unique, $new_integrity_unique)) {
                try {
                    sqlQueryBuilder()->update('pricelists_products')
                        ->directValues(['id_product' => $item['correct_id_product']])
                        ->andWhere(Operator::equals(['id' => $item['id']]))
                        ->execute();
                    $count--;
                    $this->log("Opraveno id_product {$item['pricelist_id_product']} na {$item['variation_id_product']} pro id {$item['id']} ");

                    if ($count % 100 === 0) {
                        $this->log("Zbývá opravit {$count} vazeb.");
                    }
                } catch (UniqueConstraintViolationException) {
                    // nazdar
                    // integrityUniqueCheck se provadi na urovni doctrine, chytame vyjimku misto array kontroly (měli jsme 1M+ rows)
                }
            } else {
                sqlQueryBuilder()
                    ->delete('pricelists_products')
                    ->where(Operator::equals(['id' => $item['id']]))
                    ->execute();
                $this->log('Smazaná vazba v product_pricelist s id '.$item['id'].' z důvodu chyby dat - spravna kombinace jiz existuje');
                $count--;
                if ($count % 100 === 0) {
                    $this->log("Zbývá opravit {$count} vazeb.");
                }
            }
        }
        $this->log('Oprava vazeb v product_pricelist dokončena.');
    }

    private function integrityUniqueCheck(array $values, string $new_integrity_unique): bool
    {
        if (!in_array($new_integrity_unique, $values, true)) {
            return true;
        }

        return false;
    }

    private function getData(array $arguments)
    {
        $data = sqlQueryBuilder()
            ->select('pp.id',
                'pp.id_pricelist',
                'pp.id_product AS pricelist_id_product',
                'pp.id_variation AS id_pricelist_variation',
                'pv.id_product AS correct_id_product',
                'pv.id AS id_variation')
            ->from('pricelists_products', 'pp')
            ->leftJoin('pp', 'products_variations', 'pv', 'pp.id_variation = pv.id')
            ->andWhere('pp.id_variation IS NOT NULL')
            ->andWhere('pv.id_product IS NOT NULL')
            ->andWhere('pp.id_product != pv.id_product');

        if (!empty($arguments['id_product'])) {
            $data->andWhere(Operator::equals(['pp.id_product' => $arguments['id_product']]));
        }

        return $data->execute();
    }
}

return FixProductlistCombinations::class;
