<?php

declare(strict_types=1);

namespace Plugin\tnt_coupons;

use \JTL\Smarty\JTLSmarty;
use JTL\DB\DbInterface;
use JTL\DB\ReturnType;
use JTL\Plugin\PluginInterface;
use JTL\Shop;
use JTL\Language\LanguageHelper;
use JTL\Checkout\Kupon;
use JTL\Helpers\Category;
use JTL\Session\Frontend;
use JTL\Helpers\Product;
use JTL\Statistik;
use stdClass;
use function array_filter;
use function date_create;
use function Functional\none;
use function gibGesamtsummeKuponartikelImWarenkorb;
use function in_array;
use function mb_strpos;
use function pq;
use const C_WARENKORBPOS_TYP_ARTIKEL;

class Sales
{

    private DbInterface $db;
    private PluginInterface $extension;
    private object $coupon;
    private JTLSmarty $smarty;
    private ?string $currency_symbol;

    public function __construct(PluginInterface $extension, DbInterface $db)
    {
        $this->extension = $extension;
        $this->db        = $db;
        $this->smarty    = Shop::Smarty();
        //$this->smarty->assign("tnt_coupons_active", $this->extension->getConfig()->getValue('tnt_coupons_active'));
        $this->currency_symbol = Frontend::getCurrency()->getHtmlEntity();
        $this->smarty->assign('tnt_coupons_currency_symbol', $this->currency_symbol);
        /*
        $this->smarty->assign(
            "tnt_coupons_wk_anzeige",
            $this->extension->getConfig()->getValue('tnt_coupons_wk_anzeige')
        );
        */
    }

    public function convertToSale($data, $assign = false, $showLimit = 10): stdClass
    {
        $frD        = new stdClass();
        $frD->hints = array();
        $baseURL    = Shop::getUrl();
        if (substr($baseURL, -1) !== '/') {
            $baseURL .= '/';
        }
        $lz         = $this->extension->getLocalization();
        $langHelper = LanguageHelper::getInstance();
        $langISO    = $langHelper->gibISO();
        if ($data->kKundengruppe !== ''
            && $data->kKundengruppe !== '-1'
            && (int)$data->kKundengruppe !== Frontend::getCustomerGroup()->getID()
        ) {
            $frD->hints[] = $lz->getTranslation('couponErr5', 'global');
        }
        if ($data->cArtikel !== '' && $data->cArtikel !== '-1') {
            $artikel = '';
            $cArtNr  = array_filter(explode(';', $data->cArtikel));
            if (\count($cArtNr) > 0) {
                foreach ($cArtNr as &$a_nr) {
                    $a_nr = "'" . $a_nr . "'";
                }
                $products = $this->getProducts(implode(',', $cArtNr), $langHelper->kSprache);
                foreach ($products as $pr) {
                    $cSeo  = $pr->cSeo;
                    $cName = $pr->cName;
                    if (strlen($cSeo) <= 0) {
                        $cSeo = $pr->cSeo_translated;
                    }
                    if (strlen($cName) <= 0) {
                        $cName = $pr->cName_translated;
                    }
                    if ($showLimit == 0) {
                        if (substr($artikel, -2) === ', ') {
                            $artikel = substr($artikel, 0, -2);
                        }
                        $artikel .= "<a class='d-inline-block mx-2' data-toggle='collapse' href='#clSaleArtikel' role='button' aria-expanded='false' aria-controls='clSaleArtikel'>...</a>";
                        $artikel .= "<div class='collapse' id='clSaleArtikel'>";
                    }
                    $artikel .= "<a href='" . $baseURL . $cSeo . "' target='_blank' class='text-dark'>" . strip_tags($cName) . '</a>, ';
                    $showLimit--;
                }
                if (substr($artikel, -2) === ', ') {
                    $artikel = substr($artikel, 0, -2);
                }
                if ($showLimit <= 0) {
                    $artikel .= '</div>';
                }
                $frD->hints[] = vsprintf(
                    $lz->getTranslation('tnt_coupons_lang_hints_cArtikel', $langISO),
                    array($artikel)
                );
            }
        }
        if ($data->cKategorien !== '' && $data->cKategorien !== '-1') {
            $kategorien = $this->recurseCats($data->cKategorien, Category::getInstance()->combinedGetAll());
            if (substr($kategorien, -2) === ', ') {
                $kategorien = substr($kategorien, 0, -2);
            }
            $frD->hints[] = vsprintf(
                $lz->getTranslation(
                    'tnt_coupons_lang_hints_cKategorien',
                    $langISO
                ),
                array($kategorien)
            );
        }
        if ($data->cHersteller !== '' && $data->cHersteller !== '-1') {
            $filter     = Shop::getProductFilter();
            $manuf      = $filter->getManufacturerFilter();
            $hersteller = '';
            foreach ($manuf->getOptions() as $o) {
                $val = $o->getValue();
                if (mb_strpos($data->cHersteller, $val . ';') !== false) {
                    $hersteller .= "<a href='" . $o->getURL() . "' target='_blank'>" . strip_tags($o->getName()) . '</a>, ';
                }
            }
            if (substr($hersteller, -2) === ', ') {
                $hersteller = substr($hersteller, 0, -2);
            }
            $frD->hints[] = vsprintf(
                $lz->getTranslation(
                    'tnt_coupons_lang_hints_cHersteller',
                    $langISO
                ),
                array($hersteller)
            );
        }
        if ($data->cKunden !== '' && $data->cKunden !== '-1') {
            $frD->hints[] = $langHelper->getTranslation('couponErr9', 'global');
        }
        if ((int)$data->nVerwendungen > 0) {
            $frD->hints[] = vsprintf(
                $lz->getTranslation('tnt_coupons_lang_hints_nVerwendungen', $langISO),
                array($data->nVerwendungen)
            );
            if ((int)$data->nVerwendungen <= (int)$data->nVerwendungenBisher) {
                $frD->hints[] = $langHelper->getTranslation('couponErr6', 'global');
            }
        }
        if (!empty($data->nVerwendungenProKunde) && (int)$data->nVerwendungenProKunde > 0) {
            $frD->hints[] = vsprintf(
                $lz->getTranslation('tnt_coupons_lang_hints_nVerwendungenProKunde', $langISO),
                array($data->nVerwendungenProKunde)
            );
        }
        if (intval($data->fMindestbestellwert) > 0) {
            $frD->hints[] = vsprintf(
                $lz->getTranslation('tnt_coupons_lang_hints_fMindestbestellwert', $langISO),
                array($data->fMindestbestellwert . $this->currency_symbol)
            );
        }
        if ($data->cLieferlaender !== '' && $data->cLieferlaender !== '-1') {
            $frD->hints[] = vsprintf(
                $lz->getTranslation('tnt_coupons_lang_hints_cLieferlaender', $langISO),
                array(str_replace(';', ', ', $data->cLieferlaender))
            );
        }
        if ($assign) {
            $this->smarty->assign('tnt_coupons_frD', $frD);
        }
        return $frD;
    }

    private function validateCoupon($coupon, $artikel): bool
    {
        if ($coupon->cAktiv !== 'Y') {
            return false;
        } elseif (!empty($coupon->dGueltigBis) && date_create($coupon->dGueltigBis) < date_create()) {
            return false;
        } elseif (date_create($coupon->dGueltigAb) > date_create()) {
            return false;
        }
        if ($coupon->cArtikel !== '' && $coupon->cArtikel !== '-1') {
            if ((!empty($artikel->cArtNr) && mb_strpos($coupon->cArtikel, $artikel->cArtNr . ';') === false)
                || !isset($artikel->cArtNr)
                || empty($artikel->cArtNr)
            ) {
                return false;
            }
        }
        if ($coupon->cKategorien !== '' && $coupon->cKategorien !== '-1') {
            $categories = array();
            $productID  = (int)$artikel->kArtikel;
            if (Product::isVariChild($productID)) {
                $productID = Product::getParent($productID);
            }
            $categoryIDs = $this->db->selectAll(
                'tkategorieartikel',
                'kArtikel',
                $productID,
                'kKategorie'
            );
            foreach ($categoryIDs as $categoryID) {
                $categoryID->kKategorie = (int)$categoryID->kKategorie;
                if (!in_array($categoryID->kKategorie, $categories, true)) {
                    $categories[] = $categoryID->kKategorie;
                }
            }
            $return_false = true;
            foreach ($categories as $category) {
                if (mb_strpos($coupon->cKategorien, $category . ';') !== false) {
                    $return_false = false;
                    break;
                }
            }
            if ($return_false) {
                return false;
            }
        }
        if ($coupon->cHersteller !== '' && $coupon->cHersteller !== '-1') {
            if ((!empty($artikel->kHersteller)
                    && mb_strpos($coupon->cHersteller, $artikel->kHersteller . ';') === false)
                || !isset($artikel->kHersteller)
                || empty($artikel->kHersteller)
            ) {
                return false;
            }
        }
        if ($coupon->cKunden !== '' && $coupon->cKunden !== '-1') {
            if ((!empty($_SESSION['Kunde']->kKunde)
                    && mb_strpos($coupon->cKunden, $_SESSION['Kunde']->kKunde . ';') === false)
                || !isset($_SESSION['Kunde']->kKunde)
                || empty($_SESSION['Kunde']->kKunde)
            ) {
                return false;
            }
        }
        if ($coupon->kKundengruppe !== ''
            && $coupon->kKundengruppe !== '-1'
            && (int)$coupon->kKundengruppe !== Frontend::getCustomerGroup()->getID()
        ) {
            return false;
        }
        if ($coupon->nVerwendungen > 0 && $coupon->nVerwendungen <= $coupon->nVerwendungenBisher) {
            return false;
        }
        if (!empty($coupon->nVerwendungenProKunde) && $coupon->nVerwendungenProKunde > 0) {
            if (isset($_SESSION['Kunde'])) {
                $countCouponUsed = Shop::Container()->getDB()->getSingleObject(
                    'SELECT nVerwendungen
							FROM tkuponkunde
							WHERE kKupon = :coupon
							AND cMail = :email',
                    [
                        'coupon' => (int)$coupon->kKupon,
                        'email' => Kupon::hash($_SESSION['Kunde']->cMail)
                    ]
                );
                if ($countCouponUsed !== null && $countCouponUsed->nVerwendungen >= $coupon->nVerwendungenProKunde) {
                    return false;
                }
            }
        }
        return true;
    }

    private function discount_price(&$artikel): void
    {
        $coupons = $this->getCoupons();
        $this->setCoupon($coupons);
        if (isset($this->coupon->kKupon) && $this->validateCoupon($this->coupon, $artikel)) {
            $showDiscounts = $this->getConfig($this->coupon, 'tnt_cp_check4');
            if (!\is_null($showDiscounts)) {
                if ((int)$this->coupon->fWert > 0) {
                    $art_has_discount = true;
                    if ($this->coupon->cArtikel !== '' && $this->coupon->cArtikel !== '-1') {
                        $art_has_discount = false;
                        if (!empty($artikel->cArtNr)
                            && mb_strpos($this->coupon->cArtikel, $artikel->cArtNr . ';') !== false
                        ) {
                            $art_has_discount = true;
                        }
                    }
                    if ($art_has_discount) {
                        if ($this->coupon->cWertTyp === 'prozent') {
                            $discount  = ((float)$this->coupon->fWert * (float)$artikel->Preise->fVKBrutto) / 100;
                            $new_price = (float)$artikel->Preise->fVKBrutto - $discount;
                        } else {
                            $discount  = (float)$this->coupon->fWert;
                            $new_price = (float)$artikel->Preise->fVKBrutto - $discount;
                        }
                        $new_price = \number_format(
                            \round($new_price, 2),
                            2,
                            ',',
                            '.'
                        ) . ' ' . $this->currency_symbol;

                        $discount = \number_format(
                            \round($discount, 2),
                            2,
                            ',',
                            '.'
                        ) . ' ' . $this->currency_symbol;

                        $_SESSION['tnt_coupons_product'][$artikel->kArtikel] = (object)[
                            'new_price' => $new_price,
                            'discount' => $discount,
                        ];
                    }
                }
            }
        }
    }

    public function fuelleArtikel($param): void
    {
        $this->discount_price($param['oArtikel']);
    }

    public function artikelseite($param): void
    {
        $this->discount_price($param['oArtikel']);
    }

    private function setCoupon($coupons)
    {
        $this->coupon = new stdClass();
        foreach ($coupons as $coupon) {
            if ($coupon->cAktiv !== 'Y') {
                continue;
            } elseif (!empty($coupon->dGueltigBis) && date_create($coupon->dGueltigBis) < date_create()) {
                continue;
            } elseif (date_create($coupon->dGueltigAb) > date_create()) {
                continue;
            }
            $this->coupon = $coupon;
            break;
        }
    }

    public function details($param): void
    {
        $cartVal = Frontend::getCart()->gibGesamtsummeWarenExt([C_WARENKORBPOS_TYP_ARTIKEL], true);
        if ($cartVal > 0) {
            $var_display         = 'd-none';
            $min_needed          = 0;
            $fWert               = '';
            $unit                = '';
            $fMindestbestellwert = '';
            $coupons             = $this->getCoupons();
            $this->setCoupon($coupons);
            if (isset($this->coupon->kKupon)) {
                $this->smarty->assign('tnt_coupons_sale_active', 1);
                $missing = $this->basket_missing_value($this->coupon);
                $this->smarty->assign('tnt_coupons_missing_amount', $missing);
                $var_display = 'd-flex';
                if ($missing <= 0) {
                    $reached = 'Y';
                } else {
                    $reached = 'N';
                }
                $this->smarty->assign('tnt_coupons_reached_min', $reached);
                $unit = $this->coupon->cWertTyp;
                if ($unit == 'prozent') {
                    $unit = '&#37;';
                } else {
                    $unit = ' ' . $this->currency_symbol;
                }
                $fWert = $this->coupon->fWert;
                $this->smarty->assign('tnt_coupons_basket_display', $var_display);
                $this->smarty->assign('tnt_coupons_basket_max', $min_needed);
                $this->smarty->assign(
                    'tnt_coupons_lang_var_congratulation',
                    vsprintf(
                        $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_congratulation'),
                        array(
                            $this->coupon->fMindestbestellwert . ' ' . $this->currency_symbol,
                            $fWert . ' ' . $unit, $this->coupon->cCode
                        )
                    )
                );
                $this->smarty->assign(
                    'tnt_coupons_lang_var_still_missing',
                    vsprintf(
                        $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_still_missing'),
                        array("<a href='#modalCoupons' data-bs-toggle='modal' data-toggle='modal'>"
                            . $this->coupon->fMindestbestellwert . ' ' . $this->currency_symbol . '</a>',
                            $fWert . ' ' . $unit
                        )
                    )
                );
            }
        }
    }

    private function basket_missing_value($coupon): float
    {
        $result = 0.00;
        $min    = floatval($coupon->fMindestbestellwert);
        if ($min > 0) {
            $cart = Frontend::getCart();
            if ($coupon->cWertTyp === 'festpreis' && $coupon->nGanzenWKRabattieren === '0') {
                $result = $min - gibGesamtsummeKuponartikelImWarenkorb($coupon, $cart->PositionenArr);
            } else {
                $result = $min - $cart->gibGesamtsummeWarenExt([C_WARENKORBPOS_TYP_ARTIKEL], true);
            }
        }
        if ($result > 0) {
            $result = round($result, 2);
        }
        return $result;
    }

    private function recurseCats($cKategorien, $cats)
    {
        $result = '';
        foreach ($cats as $o) {
            $id = $o->getID();
            if (mb_strpos($cKategorien, $id . ';') !== false) {
                $result .= "<a href='" . $o->getURL() . "' target='_blank'>"
                    . strip_tags($o->getShortName()) . '</a>, ';
            }
            $childs = Category::getInstance()->getChildCategoriesById($id);
            if (count($childs) > 0) {
                $result .= $this->recurseCats($cKategorien, $childs);
            }
        }
        return $result;
    }

    public function wk_hinweis(): void
    {
        $coupons = $this->getCoupons();
        $this->setCoupon($coupons);
        if (isset($this->coupon->kKupon) && !\is_null($this->getConfig($this->coupon, 'tnt_cp_check3'))) {
            $data = $this->coupon;
            $this->smarty->assign('tnt_coupons_sale_active', 1);
            $this->smarty->assign('tnt_coupons_wk_anzeige', 'Y');
            $unit = $data->cWertTyp;
            if ($unit === 'prozent') {
                $unit = '&#37;';
            } else {
                $unit = ' ' . $this->currency_symbol;
            }
            $fWert      = $data->fWert;
            $min_needed = floatval($data->fMindestbestellwert);
            $missing    = $this->basket_missing_value($data);
            if ($missing <= 0) {
                $missing = 0;
                $reached = 'Y';
            } else {
                $reached = 'N';
            }
            $this->smarty->assign('tnt_coupons_reached_min', $reached);
            $this->smarty->assign('tnt_coupons_missing_amount', $missing);
            $this->smarty->assign('tnt_coupons_currency_symbol', $this->currency_symbol);
            $this->smarty->assign('tnt_coupons_basket_display', 'd-flex');
            $this->smarty->assign('tnt_coupons_basket_max', $min_needed);
            $this->smarty->assign(
                'tnt_coupons_lang_var_congratulation',
                vsprintf(
                    $this->extension->getLocalization()->getTranslation(
                        'tnt_coupons_lang_var_congratulation'
                    ),
                    array(
                        $this->coupon->fMindestbestellwert . ' ' . $this->currency_symbol, $fWert . ' ' . $unit,
                        $data->cCode
                    )
                )
            );
            $this->smarty->assign(
                'tnt_coupons_lang_var_still_missing',
                vsprintf(
                    $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_still_missing'),
                    array(
                        "<a href='#modalCoupons' data-bs-toggle='modal' data-toggle='modal'>"
                        . $data->fMindestbestellwert . ' ' . $this->currency_symbol . '</a>',
                        $fWert . ' ' . $unit
                    )
                )
            );
        }
    }

    private function setCSS($cp): void
    {
        $_balkenColor = $this->getConfig($cp, 'tnt_cp_color1');
        if (!is_null($_balkenColor)) {
            $this->smarty->assign(
                'tnt_coupons_balkenColor',
                'background-color: ' . $_balkenColor . '!important;'
            );
        }
        $_txtColor = $this->getConfig($cp, 'tnt_cp_color2');
        if (!is_null($_txtColor)) {
            $this->smarty->assign('tnt_coupons_txtColor', 'color: ' . $_txtColor . '!important;');
        }
    }

    public function init(): void
    {
        $coupons = $this->getCoupons();
        $this->setCoupon($coupons);
        if (isset($this->coupon->kKupon)) {
            $data = $this->coupon;
            $this->smarty->assign('tnt_coupons_sale_active', 1);
            $data->localizedName = $this->getCouponTranslation($data->kKupon);
            $this->smarty->assign('tnt_coupons_title', $data->localizedName);
            $this->setCSS($data);
            $time_remaining = null;
            $days_remaining = null;
            $unit           = $data->cWertTyp;
            if ($unit == 'prozent') {
                $unit = '&#37;';
            } else {
                $unit = ' ' . $this->currency_symbol;
            }

            $showPupup        = $this->getConfig($data, 'tnt_cp_file');
            $popupSize        = $this->getConfig($data, 'tnt_cp_popupSize');
            $popupDescription = $this->getConfig($data, 'tnt_cp_description');

            if (!is_null($showPupup) || !is_null($popupDescription)) {
                if (time() > strtotime($data->dGueltigAb)) {
                    if (isset($_SESSION['tnt_cp_popup_shown']) && $_SESSION['tnt_cp_popup_shown'] === $data->kKupon) {
                        $_SESSION['tnt_cp_popup_shown'] = $data->kKupon;
                    } else {
                        $file = $this->extension->getPaths()->getFrontendPath() . 'template/popup.tpl';
                        $this->smarty->assign('tnt_cp_popupShow', 1);
                        $this->smarty->assign('tnt_cp_popupTitle', $data->localizedName);
                        $this->smarty->assign('tnt_cp_popupImg', $showPupup);
                        $this->smarty->assign('tnt_cp_popupSize', $popupSize ?? '');
                        $this->smarty->assign('tnt_cp_popupDescription', $popupDescription);
                        $tpl = $this->smarty->fetch($file);
                        pq('body')->append($tpl);
                    }
                    $_SESSION['tnt_cp_popup_shown'] = $data->kKupon;
                }
            }

            if (!empty($data->dGueltigBis) && !\is_null($this->getConfig($this->coupon, 'tnt_cp_check2'))) {
                $time_remaining = time();
                $time_remaining = abs($time_remaining - strtotime($data->dGueltigBis));
                $days_remaining = floor($time_remaining / 86400);
                $time_remaining = $time_remaining - ($days_remaining * 86400);
                $tmp            = new stdClass();
                $tmp->hours     = floor($time_remaining / 3600);
                $tmp->minutes   = floor(($time_remaining / 60) - ($tmp->hours * 60));
                $tmp->seconds   = floor(((($time_remaining / 60) - ($tmp->hours * 60)) - $tmp->minutes) * 60);
                if ($tmp->hours < 10) {
                    $tmp->hours = '0' . $tmp->hours;
                }
                if ($tmp->minutes < 10) {
                    $tmp->minutes = '0' . $tmp->minutes;
                }
                if ($tmp->seconds < 10) {
                    $tmp->seconds = '0' . $tmp->seconds;
                }
                $time_remaining = $tmp;
            }

            $this->smarty->assign('tnt_coupons_discount', $data->fWert . $unit);

            $this->smarty->assign(
                'tnt_coupons_lang_var_total_discount',
                $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_total_discount')
            );
            $this->smarty->assign(
                'tnt_coupons_discount_text',
                vsprintf(
                    $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_get_discount'),
                    array($data->fWert . ' ' . $unit)
                )
            );
            $this->smarty->assign(
                'tnt_coupons_lang_var_discount_code',
                $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_discount_code')
            );
            $this->smarty->assign(
                'tnt_coupons_lang_var_type_in',
                $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_type_in')
            );
            $this->smarty->assign(
                'tnt_coupons_lang_var_type_in_basket',
                $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_type_in_basket')
            );
            $this->smarty->assign(
                'tnt_coupons_lang_var_details',
                $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_details')
            );
            $this->smarty->assign(
                'tnt_coupons_lang_var_got_it',
                $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_got_it')
            );

            $this->smarty->assign(
                'tnt_coupons_lang_var_bis_zu',
                $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_bis_zu')
            );
            $this->smarty->assign(
                'tnt_coupons_lang_var_noch',
                $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_noch')
            );
            if (!is_null($time_remaining) && !is_null($days_remaining)) {
                $this->smarty->assign('tnt_coupons_time_remaining', $time_remaining);
                $this->smarty->assign('tnt_coupons_days_remaining', $days_remaining);
            }

            $days_or_day = $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_day');
            if ($days_remaining > 1) {
                $days_or_day = $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_days');
            }
            $this->smarty->assign('tnt_coupons_lang_var_days', $days_or_day);
            $this->smarty->assign('tnt_coupons_code', $data->cCode);
            $this->smarty->assign(
                'tnt_coupons_show_modal',
                !\is_null($this->getConfig($this->coupon, 'tnt_cp_check6'))
            );

            $langHelper = LanguageHelper::getInstance();

            $this->convertToSale($data, true);

            $layout        = '';
            $layout_config = $this->getConfig($data, 'tnt_cp_layout');
            if (!is_null($layout_config)) {
                if ($layout_config === 'menu') {
                    $layout = 'header:not(#opcHeader)';
                } elseif ($layout_config === 'header') {
                    $layout = 'body';
                }
            }
            if ($layout !== '') {
                $file = $this->extension->getPaths()->getFrontendPath() . 'template/sales_action.tpl';
                $tpl  = $this->smarty->fetch($file);
                if ($layout === 'body') {
                    pq($layout)->prepend($tpl);
                } else {
                    pq($layout)->append($tpl);
                }
            }
            $file = $this->extension->getPaths()->getFrontendPath() . 'template/footer.tpl';
            $tpl  = $this->smarty->fetch($file);
            pq('footer')->append($tpl);
        } else {
            $coupons = $this->getCoupons();
            $cp      = new stdClass();
            foreach ($coupons as $coupon) {
                if ($coupon->cAktiv !== 'Y') {
                    continue;
                } elseif (!empty($coupon->dGueltigBis) && date_create($coupon->dGueltigBis) < date_create()) {
                    continue;
                } elseif (empty($coupon->dGueltigAb)) {
                    continue;
                }
                $showCD_start = $this->getConfig($coupon, 'tnt_cp_check1');
                if (!\is_null($showCD_start)) {
                    $cp = $coupon;
                    break;
                }
            }
            if (isset($cp->kKupon)) {
                $layout        = '';
                $layout_config = $this->getConfig($cp, 'tnt_cp_layout');
                if (!is_null($layout_config)) {
                    if ($layout_config === 'menu') {
                        $layout = 'header:not(#opcHeader)';
                    } elseif ($layout_config === 'header') {
                        $layout = 'body';
                    }
                }
                if ($layout !== '') {
                    $this->setCSS($cp);
                    $lz                = $this->extension->getLocalization();
                    $cp->localizedName = $this->getCouponTranslation($cp->kKupon);
                    $this->smarty->assign('tnt_coupons_title', $cp->localizedName);
                    $unit = $cp->cWertTyp;
                    if ($unit == 'prozent') {
                        $unit = '&#37;';
                    } else {
                        $unit = ' ' . $this->currency_symbol;
                    }
                    $this->smarty->assign(
                        'tnt_coupons_discount',
                        $cp->fWert . $unit
                    );
                    $this->smarty->assign(
                        'tnt_coupons_lang_var_bis_zu',
                        $lz->getTranslation('tnt_coupons_lang_var_bis_zu')
                    );
                    $this->smarty->assign(
                        'tnt_coupons_lang_var_noch',
                        $lz->getTranslation('tnt_coupons_lang_var_startet_in')
                    );

                    $this->smarty->assign(
                        'tnt_coupons_lang_var_total_discount',
                        $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_total_discount')
                    );
                    $this->smarty->assign(
                        'tnt_coupons_discount_text',
                        vsprintf(
                            $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_get_discount'),
                            array($cp->fWert . ' ' . $unit)
                        )
                    );
                    $this->smarty->assign(
                        'tnt_coupons_lang_var_discount_code',
                        $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_discount_code')
                    );
                    $this->smarty->assign(
                        'tnt_coupons_lang_var_type_in',
                        $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_type_in')
                    );
                    $this->smarty->assign(
                        'tnt_coupons_lang_var_type_in_basket',
                        $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_type_in_basket')
                    );
                    $this->smarty->assign(
                        'tnt_coupons_lang_var_details',
                        $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_details')
                    );
                    $this->smarty->assign(
                        'tnt_coupons_lang_var_got_it',
                        $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_got_it')
                    );
                    $this->smarty->assign(
                        'tnt_coupons_code',
                        $cp->cCode
                    );

                    $time_remaining = time();
                    $time_remaining = abs($time_remaining - strtotime($cp->dGueltigAb));
                    $days_remaining = floor($time_remaining / 86400);
                    $time_remaining = $time_remaining - ($days_remaining * 86400);
                    $tmp            = new stdClass();
                    $tmp->hours     = floor($time_remaining / 3600);
                    $tmp->minutes   = floor(($time_remaining / 60) - ($tmp->hours * 60));
                    $tmp->seconds   = floor(((($time_remaining / 60) - ($tmp->hours * 60)) - $tmp->minutes) * 60);
                    if ($tmp->hours < 10) {
                        $tmp->hours = '0' . $tmp->hours;
                    }
                    if ($tmp->minutes < 10) {
                        $tmp->minutes = '0' . $tmp->minutes;
                    }
                    if ($tmp->seconds < 10) {
                        $tmp->seconds = '0' . $tmp->seconds;
                    }
                    $time_remaining = $tmp;

                    $days_or_day = $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_day');
                    if ($days_remaining > 1) {
                        $days_or_day = $this->extension->getLocalization()->getTranslation('tnt_coupons_lang_var_days');
                    }
                    if ($days_remaining > 0) {
                        $this->smarty->assign('tnt_coupons_days_remaining', $days_remaining);
                        $this->smarty->assign('tnt_coupons_lang_var_days', $days_or_day);
                    }

                    $this->convertToSale($cp, true);

                    $this->smarty->assign('tnt_coupons_time_remaining', $time_remaining);
                    $this->smarty->assign(
                        'tnt_coupons_show_modal',
                        !\is_null($this->getConfig($this->coupon, 'tnt_cp_check6'))
                    );
                    $file = $this->extension->getPaths()->getFrontendPath() . 'template/sales_action.tpl';
                    $tpl  = $this->smarty->fetch($file);

                    if ($layout === 'body') {
                        pq($layout)->prepend($tpl);
                    } else {
                        pq($layout)->append($tpl);
                    }
                    $file = $this->extension->getPaths()->getFrontendPath() . 'template/footer.tpl';
                    $tpl  = $this->smarty->fetch($file);
                    pq('footer')->append($tpl);
                }
            }
        }
    }

    private function angabenKorrekt(array $missingData): int
    {
        return (int)none($missingData, static function ($e) {
            return $e > 0;
        });
    }

    private function getConfig($coupon, $key = '')
    {
        $result = \json_decode($coupon->textra ?? '{}');
        if ($key !== '') {
            $result = $result->{$key} ?? null;
        }
        return $result;
    }

    public function applyCoupon()
    {
        $coupons = $this->getCoupons();
        $this->setCoupon($coupons);
        if (isset($this->coupon->cCode)) {
            if ($this->coupon->cCode != '') {
                $autoApply = $this->getConfig($this->coupon, 'tnt_cp_check5');
                if (!is_null($autoApply)) {
                    $this->plausiKupon($this->coupon->cCode);
                }
            }
        }
    }

    public function plausiKupon($code = '')
    {
        $cartVal = Frontend::getCart()->gibGesamtsummeWarenExt([C_WARENKORBPOS_TYP_ARTIKEL], true);
        if ($cartVal <= 0) {
            return 0;
        }
        $errors = [];
        $coupon = new Kupon();
        if ($code === '') {
            if (isset($this->coupon->cCode)) {
                if ($this->coupon->cCode != '') {
                    $code = $this->coupon->cCode;
                }
            }
        }
        $coupon = $coupon->getByCode($code);
        if ($coupon !== false && $coupon->kKupon > 0) {
            $errors = Kupon::checkCoupon($coupon);
            if (count($errors) == 0) {
                if ($this->angabenKorrekt($errors)) {
                    Kupon::acceptCoupon($coupon);
                    if ($coupon->cKuponTyp === Kupon::TYPE_SHIPPING) {
                        //$_SESSION['oVersandfreiKupon'] = $coupon;
                    }
                }
            } else {
                return 0;
            }
        } else {
            $errors['ungueltig'] = 11;
        }
        Kupon::mapCouponErrorMessage($errors['ungueltig'] ?? 0);
        $this->plausiNeukundenKupon();
        return (count($errors) > 0)
            ? $errors
            : 0;
    }

    private function plausiNeukundenKupon()
    {
        if (isset($_SESSION['NeukundenKuponAngenommen']) && $_SESSION['NeukundenKuponAngenommen'] === true) {
            return;
        }
        $customer = Frontend::getCustomer();
        if ((!isset($_SESSION['Kupon']->cKuponTyp)
                || $_SESSION['Kupon']->cKuponTyp !== 'standard')
            && !empty($customer->cMail)
        ) {
            $conf = Shop::getSettings([CONF_KAUFABWICKLUNG]);
            if ($customer->getID() <= 0
                && $conf['kaufabwicklung']['bestellvorgang_unregneukundenkupon_zulassen'] === 'N'
            ) {
                // unregistrierte Neukunden, keine Kupons für Gastbestellungen zugelassen
                return;
            }
            // not for already registered customers with order(s)
            if ($customer->getID() > 0) {
                $order = Shop::Container()->getDB()->getSingleObject(
                    'SELECT kBestellung
						FROM tbestellung
						WHERE kKunde = :customerID
						LIMIT 1',
                    ['customerID' => $customer->getID()]
                );
                if ($order !== null) {
                    return;
                }
            }
            $coupons = (new Kupon())->getNewCustomerCoupon();
            if (!empty($coupons) && !Kupon::newCustomerCouponUsed($customer->cMail)) {
                foreach ($coupons as $coupon) {
                    if ($this->angabenKorrekt(Kupon::checkCoupon($coupon))) {
                        Kupon::acceptCoupon($coupon);
                        break;
                    }
                }
            }
        }
    }

    /**
     * @param $kKupon
     * @return object{nVerwendungenBisher: int, dGueltigAb: string, dGueltigBis: string, cName: string, Gespart: float,
     *  totalOrders: int, umsatzSale: array, umsatzDavor: array, dGueltigAbFormat: string, dGueltigBisFormat: string,
     *  chart: string}
     */
    public function stats($kKupon): object
    {
        $data = $this->db->queryPrepared(
            'SELECT tkupon.nVerwendungenBisher, tkupon.dGueltigAb, tkupon.dGueltigBis,
       tkuponsprache.cName AS Titel, SUM(tkuponbestellung.fKuponwertBrutto) AS Gespart
				FROM tkupon
				LEFT JOIN tkuponsprache
				ON tkupon.kKupon = tkuponsprache.kKupon AND tkuponsprache.cISOSprache = :lang
				LEFT JOIN tkuponbestellung
				ON tkupon.kKupon = tkuponbestellung.kKupon
				WHERE tkupon.kKupon = :kupon
				GROUP BY tkupon.kKupon',
            [
                'kupon' => (int)$kKupon,
                'lang' => 'ger'
            ],
            ReturnType::SINGLE_OBJECT
        );

        $data->totalOrders = 0;

        $von = $data->dGueltigAb ?? null;
        if (!is_null($von)) {
            $bis   = $data->dGueltigBis ?? \date_create()->format('Y-m-d H:i:s');
            $stats = new Statistik(\strtotime($von), \strtotime($bis));
            $stats->getAnzeigeIntervall();
            $umsatz           = $stats->holeUmsatzStats();
            $data->umsatzSale = $umsatz;

            $days = $stats->getAnzahlTage();

            $stats->setDatumStampVon(strtotime($von . '-' . $days . ' day'));
            $stats->setDatumStampBis(strtotime($bis . '-' . $days . ' day'));
            $stats->getAnzeigeIntervall();
            $umsatz            = $stats->holeUmsatzStats();
            $data->umsatzDavor = $umsatz;

            $orders = $this->db->queryPrepared(
                'SELECT COUNT(tbestellung.kBestellung) AS bestellungen
					FROM tbestellung
					WHERE tbestellung.fGesamtsumme > 0
					AND tbestellung.dErstellt BETWEEN :_von AND :_bis',
                ['_von' => $von, '_bis' => $bis],
                ReturnType::SINGLE_OBJECT
            );

            $data->dGueltigAbFormat  = '';
            $data->dGueltigBisFormat = '';
            $data->chart             = '';
            $data->totalOrders       = (int)$orders->bestellungen;
        }

        return $data;
    }

    public function getCoupons($all = false): array
    {
        if ($all) {
            $cps = $this->db->queryPrepared(
                'SELECT tkupon.*, tkuponsprache.cName AS Titel, SUM(tkuponbestellung.fKuponwertBrutto) AS Gespart,
                    tnt_coupons_config.textra
					FROM tkupon
					LEFT JOIN tkuponsprache
					ON tkupon.kKupon = tkuponsprache.kKupon AND tkuponsprache.cISOSprache = :lang
					LEFT JOIN tkuponbestellung
					ON tkupon.kKupon = tkuponbestellung.kKupon
					RIGHT JOIN tnt_coupons_config
					ON tkupon.kKupon = tnt_coupons_config.tvalue AND tnt_coupons_config.tkey = :key
					WHERE tkupon.cKuponTyp = :cKuponTyp
					GROUP BY tkupon.kKupon, tkupon.dGueltigAb
					ORDER BY tkupon.dGueltigAb DESC',
                [
                    'lang' => 'ger',
                    'key' => 'kupon',
                    'cKuponTyp' => 'standard'
                ],
                ReturnType::ARRAY_OF_OBJECTS
            );
        } else {
            $cps = $this->db->queryPrepared(
                'SELECT tkupon.*, tnt_coupons_config.textra
					FROM tkupon
					RIGHT JOIN tnt_coupons_config
					ON tkupon.kKupon = tnt_coupons_config.tvalue AND tnt_coupons_config.tkey = :tkey
					WHERE cKuponTyp = :cKuponTyp
					ORDER BY tkupon.dGueltigAb ASC',
                [
                    'cKuponTyp' => 'standard',
                    'tkey' => 'kupon'
                ],
                ReturnType::ARRAY_OF_OBJECTS
            );
        }
        return $cps;
    }

    private function getCouponTranslation($kKupon): string
    {
        if (isset($_SESSION['currentLanguage']->iso)) {
            return $this->db->queryPrepared(
                'SELECT tkuponsprache.cName
                FROM tkuponsprache
                WHERE tkuponsprache.kKupon = :kuponID AND tkuponsprache.cISOSprache = :langISO',
                [
                    'kuponID' => $kKupon,
                    'langISO' => $_SESSION['currentLanguage']->iso
                ],
                ReturnType::SINGLE_OBJECT
            )->cName ?? '';
        }

        return '';
    }

    private function getProducts($artNrs, $langID): array
    {
        return $this->db->queryPrepared(
            'SELECT tartikel.cName, tartikel.cSeo, tartikelsprache.cName AS cName_translated,
       tartikelsprache.cSeo AS cSeo_translated
				FROM tartikel
				LEFT JOIN tartikelsprache
				ON tartikelsprache.kArtikel = tartikel.kArtikel AND tartikelsprache.kSprache = :langID
				WHERE tartikel.cArtNr IN (:ArtNrs) AND tartikel.kVaterArtikel = 0',
            [
                'langID' => (int)$langID,
                'ArtNrs' => $artNrs
            ],
            ReturnType::ARRAY_OF_OBJECTS
        );
    }
}
