<?php

namespace Myvetshop\Module\Clinique\Import\Sync\Syncer;

use Myvetshop\Module\Clinique\Import\Model\CartRuleModel;
use Myvetshop\Module\Clinique\Import\Sync\SyncStatistics;

class CartRuleSyncer
{
    private \Db $db;

    protected function getExistingCartRule(CartRuleModel $cartRuleModel): ?\CartRule
    {
        $cartRuleRaw = $this->db->getRow(
            'SELECT cr.*'
            . ' FROM ' . _DB_PREFIX_ . 'cart_rule cr'
            . ' WHERE cr.code = "' . $this->db->escape($cartRuleModel->code) . '"',
            false,
        );

        if (!\is_array($cartRuleRaw)) {
            return null;
        }

        return new \CartRule($cartRuleRaw['id_cart_rule']);
    }

    protected function getCartRule(CartRuleModel $cartRuleModel): \CartRule
    {
        return $this->getExistingCartRule($cartRuleModel) ?? new \CartRule();
    }

    protected function syncCartRuleRestriction(\CartRule $cartRule): void
    {
        // Product Rule Group
        $cartRuleProductRuleGroups = $this->db->executeS(
            'SELECT * FROM ' . _DB_PREFIX_ . 'cart_rule_product_rule_group'
            . ' WHERE id_cart_rule = ' . (int) $cartRule->id
        );

        if (!\is_array($cartRuleProductRuleGroups) || empty($cartRuleProductRuleGroups)) {
            if (
                !$this->db->insert(
                    'cart_rule_product_rule_group',
                    [
                        'id_cart_rule' => (int) $cartRule->id,
                        'quantity' => 1,
                    ],
                    false,
                    false,
                )
            ) {
                throw new \Exception('cart_rule_product_rule_group INSERT ERROR');
            }

            $cartRuleProductRuleGroups = [
                [
                    'id_product_rule_group' => (int) $this->db->Insert_ID(),
                    'id_cart_rule' => (int) $cartRule->id,
                    'quantity' => 1,
                ],
            ];
        }

        if (\count($cartRuleProductRuleGroups) !== 1) {
            throw new \Exception('MULTIPLE cart_rule_product_rule_groups');
        }

        // Product Rule
        $cartRuleProductRules = $this->db->executeS(
            'SELECT * FROM ' . _DB_PREFIX_ . 'cart_rule_product_rule'
            . ' WHERE id_product_rule_group = ' . (int) $cartRuleProductRuleGroups[0]['id_product_rule_group']
        );

        if (!\is_array($cartRuleProductRules) || empty($cartRuleProductRules)) {
            if (
                !$this->db->insert(
                    'cart_rule_product_rule',
                    [
                        'id_product_rule_group' => (int) $cartRuleProductRuleGroups[0]['id_product_rule_group'],
                        'type' => 'categories',
                    ],
                    false,
                    false,
                )
            ) {
                throw new \Exception('cart_rule_product_rule_group INSERT ERROR');
            }

            $cartRuleProductRules = [
                [
                    'id_product_rule' => (int) $this->db->Insert_ID(),
                    'id_product_rule_group' => (int) $cartRuleProductRuleGroups[0]['id_product_rule_group'],
                    'type' => 'categories',
                ],
            ];
        }

        if (\count($cartRuleProductRules) !== 1) {
            throw new \Exception('MULTIPLE cart_rule_product_rule');
        }

        // Product Rule Values
        if (!$this->db->execute('INSERT IGNORE INTO ' . _DB_PREFIX_ . 'cart_rule_product_rule_value'
            . ' (id_product_rule, id_item) VALUES'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 17),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 25),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 32),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 28),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 29),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 30),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 31),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 617),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 620),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 615),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 621),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 652),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 653),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 655),'
            . ' (' . (int) $cartRuleProductRules[0]['id_product_rule'] . ', 624)'
        )) {
            throw new \Exception('cart_rule_product_rule_value INSERT ERROR');
        }
    }

    public function __construct(\Db $db)
    {
        $this->db = $db;
    }

    /**
     * @param SyncStatistics $syncStatistics
     * @param \Customer $customer
     * @param list<CartRuleModel> $cartRules
     *
     * @return array<string, \CartRule>
     */
    public function sync(
        SyncStatistics $syncStatistics,
        \Customer $customer,
        array $cartRules
    ): array {
        $ret = [];

        $cartRules = \array_values(
            \array_filter(
                $cartRules,
                function (CartRuleModel $cartRuleModel): bool {
                    return \str_starts_with($cartRuleModel->code, 'ALIM');
                }
            )
        );

        foreach ($cartRules as $cartRuleModel) {
            $ret[$cartRuleModel->code] = $this->syncCartRule(
                $syncStatistics,
                $customer,
                $cartRuleModel
            );
        }

        return $ret;
    }

    public function syncCartRule(
        SyncStatistics $syncStatistics,
        \Customer $customer,
        CartRuleModel $cartRuleModel
    ): \CartRule {
        $cartRule = $this->getCartRule($cartRuleModel);

        if ($cartRule->id) {
            ++$syncStatistics->nbCartRuleUpdated;

            $cartRule->reduction_tax = true;
            $cartRule->partial_use = false;
            $cartRule->product_restriction = true;
            $cartRule->save();

            $this->syncCartRuleRestriction($cartRule);

            return $cartRule;
        }

        $cartRule->id_customer = (int) $customer->id;
        $cartRule->name = [1 => $cartRuleModel->name];
        $cartRule->date_from = $cartRuleModel->dateFrom->format('Y-m-d H:i:s');
        $cartRule->date_to = $cartRuleModel->dateTo->format('Y-m-d H:i:s');
        $cartRule->description = $cartRuleModel->description;
        $cartRule->quantity = $cartRuleModel->quantity;
        $cartRule->highlight = true;
        $cartRule->code = $cartRuleModel->code;
        $cartRule->reduction_amount = $cartRuleModel->reductionAmount;
        $cartRule->reduction_tax = true;
        $cartRule->partial_use = false;
        $cartRule->active = $cartRuleModel->active;
        $cartRule->product_restriction = true;
        $cartRule->date_add = $cartRuleModel->dateAdd->format('Y-m-d H:i:s');
        $cartRule->date_upd = $cartRuleModel->dateAdd->format('Y-m-d H:i:s');

        ++$syncStatistics->nbCartRuleCreated;

        $cartRule->save(false, false);

        $this->syncCartRuleRestriction($cartRule);

        return $cartRule;
    }
}
