<?php

declare(strict_types=1);

namespace Plugin\tnt_coupons;

use DateTimeImmutable;
use JTL\Events\Dispatcher;
use JTL\Plugin\Bootstrapper;
use JTL\Shop;
use JTL\Smarty\JTLSmarty;
use Plugin\tnt_coupons\src\Helper\ChartDataBuilder;
use Plugin\tnt_coupons\src\Helper\WeekdayLabels;
use stdClass;

use function is_scalar;

use const HOOK_ARTIKEL_CLASS_FUELLEARTIKEL;
use const HOOK_ARTIKEL_PAGE;
use const HOOK_LETZTERINCLUDE_INC;
use const HOOK_SMARTY_OUTPUTFILTER;
use const HOOK_SHOP_SET_PAGE_TYPE;
use const HOOK_WARENKORB_PAGE;

/** @phpstan-import-type CouponRow from Sales */
class Bootstrap extends Bootstrapper
{
    private Sales $sales;

    private function getUri(): string
    {
        $requestUri = $_SERVER['REQUEST_URI'] ?? '';
        $uri        = strtok($requestUri, '?');

        return is_string($uri) ? $uri : '';
    }

    private function formatDate(?string $value): string
    {
        if ($value === null || $value === '') {
            return '';
        }

        $date = \date_create_immutable($value);

        return $date instanceof DateTimeImmutable
            ? $date->format('d.m.Y H:i')
            : '';
    }

    /** @param CouponRow $coupon */
    private function buildAdminCoupon(object $coupon, stdClass $details): stdClass
    {
        $saleImg = '';
        if ($coupon->textra !== '') {
            $json = \json_decode($coupon->textra);
            if ($json instanceof stdClass && is_scalar($json->tnt_cp_file ?? null)) {
                $saleImg = (string)$json->tnt_cp_file;
            }
        }

        $adminCoupon = (object)[
            'kKupon'                => $coupon->kKupon,
            'kKundengruppe'         => $coupon->kKundengruppe,
            'cArtikel'              => $coupon->cArtikel,
            'cKategorien'           => $coupon->cKategorien,
            'cHersteller'           => $coupon->cHersteller,
            'cKunden'               => $coupon->cKunden,
            'nVerwendungen'         => $coupon->nVerwendungen,
            'nVerwendungenBisher'   => $coupon->nVerwendungenBisher,
            'nVerwendungenProKunde' => $coupon->nVerwendungenProKunde,
            'fMindestbestellwert'   => $coupon->fMindestbestellwert,
            'cLieferlaender'        => $coupon->cLieferlaender,
            'cAktiv'                => $coupon->cAktiv,
            'dGueltigAb'            => $coupon->dGueltigAb,
            'dGueltigBis'           => $coupon->dGueltigBis,
            'cWertTyp'              => $coupon->cWertTyp,
            'fWert'                 => $coupon->fWert,
            'nGanzenWKRabattieren'  => $coupon->nGanzenWKRabattieren,
            'cCode'                 => $coupon->cCode,
            'cName'                 => $coupon->cName,
            'textra'                => $coupon->textra,
            'localizedName'         => $coupon->localizedName,
            'Titel'                 => $coupon->Titel,
            'Gespart'               => $coupon->Gespart,
            'dGueltigAbFormat'      => $this->formatDate($coupon->dGueltigAb),
            'dGueltigBisFormat'     => $this->formatDate($coupon->dGueltigBis),
            'sale_img'              => $saleImg,
            'details'               => isset($details->hints) ? $details->hints : ['-'],
        ];

        return $adminCoupon;
    }

    /**
     * Legacy hook-dispatch method, kept as-is until the roadmap refactor.
     *
     * @SuppressWarnings("PHPMD.CyclomaticComplexity")
     * @SuppressWarnings("PHPMD.ExcessiveMethodLength")
     */
    public function boot(Dispatcher $dispatcher)
    {
        parent::boot($dispatcher);

        $plugin      = $this->getPlugin();
        $db          = $this->getDB();
        $this->sales = new Sales(
            $plugin,
            $db
        );
        if (Shop::isFrontend() === false) {
            $couponConfigRow = $db->selectSingleRow(
                'tnt_coupons_config',
                ['tkey', 'tvalue'],
                ['kupon', 0]
            );
            $updateCoupons   = $couponConfigRow?->textra;
            if (!empty($updateCoupons)) {
                $couponRow   = $db->selectSingleRow('tkupon', 'cName', $updateCoupons);
                $getCouponID = (int)($couponRow?->kKupon);
                if ($getCouponID > 0) {
                    $db->deleteRow(
                        'tnt_coupons_config',
                        ['tkey', 'textra'],
                        ['kupon', $updateCoupons]
                    );
                    $obj         = new stdClass();
                    $obj->tkey   = 'kupon';
                    $obj->tvalue = $getCouponID;
                    $obj->textra = '';
                    $db->insertRow('tnt_coupons_config', $obj);
                }
            }
            if (
                $this->getUri() === '/admin/kupons.php' // Kompabilität Shop <= 5.2
                || $this->getUri() === '/admin/coupons'
            ) {
                if (
                    isset($_POST['action'], $_POST['kKupon_arr'])
                    && $_POST['action'] === 'loeschen'
                    && count($_POST['kKupon_arr']) > 0
                ) {
                    foreach ($_POST['kKupon_arr'] as $k) {
                        $db->deleteRow(
                            'tnt_coupons_config',
                            ['tkey', 'tvalue'],
                            ['kupon', (int)$k]
                        );
                    }
                }

                if (isset($_POST['tnt_coupons_sale'])) {
                    $kKupon = 0;
                    if (isset($_POST['kKuponBearbeiten'])) {
                        $kKupon = $_POST['kKuponBearbeiten'];
                        if ($kKupon === '') {
                            $kKupon = 0;
                        }
                        $kKupon = (int)$kKupon;
                        if ($kKupon > 0) { // Kupon wird bearbeitet
                            if ($_POST['tnt_coupons_sale'] === '1') {
                                if (
                                    $db->selectSingleRow(
                                        'tnt_coupons_config',
                                        ['tkey', 'tvalue'],
                                        ['kupon', $kKupon]
                                    ) === null
                                ) {
                                    $obj         = new stdClass();
                                    $obj->tkey   = 'kupon';
                                    $obj->tvalue = $kKupon;
                                    $obj->textra = '';
                                    $db->insertRow('tnt_coupons_config', $obj);
                                }
                            } else {
                                $db->deleteRow(
                                    'tnt_coupons_config',
                                    ['tkey', 'tvalue'],
                                    ['kupon', $kKupon]
                                );
                            }
                        } elseif (!empty($_POST['cName'])) {
                            $obj         = new stdClass();
                            $obj->tkey   = 'kupon';
                            $obj->tvalue = 0;
                            $obj->textra = $_POST['cName'];
                            $db->insertRow('tnt_coupons_config', $obj);
                        }
                    }
                } else {
                    if (isset($_GET['kKupon'])) {
                        $kKupon = $_GET['kKupon'];
                        if ($kKupon === '') {
                            $kKupon = 0;
                        }
                        $kKupon       = (int)$kKupon;
                        $default_ja   = '';
                        $default_nein = ' selected';
                        $is_a_sale    = new stdClass();
                        if ($kKupon > 0) {
                            $is_a_sale = $db->selectSingleRow(
                                'tnt_coupons_config',
                                ['tkey', 'tvalue'],
                                ['kupon', $kKupon]
                            );
                        }
                        if (
                            ((int)($_GET['sale'] ?? 0)) === 1
                            || isset($is_a_sale->tkey)
                        ) {
                            $default_ja   = ' selected';
                            $default_nein = '';
                        }
                        echo "<script type='text/javascript'>document.addEventListener('DOMContentLoaded', function(e){var container = $(\"#content form .card-footer.save-wrapper\");container.before(\"<div class='card settings'><div class='card-header'><div class='subheading1'>Sales Aktionen</div><hr class='mb-n3'></div><div class='card-body'><div class='form-group form-row align-items-center'><label class='col col-sm-4 col-form-label text-sm-right' for='tnt_coupons_sale'>Kupon als Sale Aktion verwenden?</label><div class='col-sm pl-sm-3 pr-sm-5 order-last order-sm-2'><select name='tnt_coupons_sale' id='tnt_coupons_sale' class='custom-select combo'><option value='1'" . $default_ja . ">Ja</option><option value='0'" . $default_nein . ">Nein</option></select></div><div class='col-auto ml-sm-n4 order-2 order-sm-3'><span data-html='true' data-toggle='tooltip' data-placement='left' title='' data-original-title='Aktivieren Sie diesen Kupon als Sale'><span class='fas fa-info-circle fa-fw'></span></span></div></div></div>\");});</script>";
                    }
                }
            } elseif (
                $this->getUri() === '/admin/plugin.php'
                || $this->getUri() === '/admin/plugin/' . $plugin->getID()
            ) {
                if (isset($_GET['tnt_coupon_stats'])) {
                    // Load Sale Statistics
                    $kKupon = $_GET['kupon'];
                    if ($kKupon === '') {
                        $kKupon = 0;
                    }
                    $kKupon                  = (int)$kKupon;
                    $data                    = $this->sales->stats($kKupon);
                    $data->dGueltigAbFormat  = $this->formatDate($data->dGueltigAb);
                    $data->dGueltigBisFormat = $this->formatDate($data->dGueltigBis);

                    $chartData   = ChartDataBuilder::build($data->umsatzDavor, $data->umsatzSale);
                    $data->chart = Shop::Smarty()->assign('baseURL', Shop::getURL())
                        ->assign('chart_data', \json_encode($chartData))
                        ->fetch(__DIR__ . '/chart.tpl');
                    echo \json_encode($data);
                    exit();
                }

                if (isset($_GET['tnt_coupon_sale'])) {
                    $kKupon          = (int)($_GET['kupon'] ?? 0);
                    $couponConfigRow = $kKupon > 0
                        ? $db->selectSingleRow(
                            'tnt_coupons_config',
                            ['tkey', 'tvalue'],
                            ['kupon', $kKupon]
                        )
                        : null;
                    $couponConfig    = $couponConfigRow?->textra;
                    echo ($couponConfig === null || $couponConfig === '') ? '{}' : $couponConfig;
                    exit();
                }
            }

            return;
        }

        unset($_SESSION['tnt_coupons_product']);
        $dispatcher->listen('shop.hook.'
            . HOOK_SMARTY_OUTPUTFILTER, [$this->sales, 'init']);
        $dispatcher->listen('shop.hook.'
            . HOOK_LETZTERINCLUDE_INC, [$this->sales, 'wkHinweis']);
        $dispatcher->listen('shop.hook.'
            . HOOK_WARENKORB_PAGE, [$this->sales, 'wkHinweis']);
        $dispatcher->listen('shop.hook.'
            . HOOK_ARTIKEL_PAGE, [$this->sales, 'artikelseite']);
        $dispatcher->listen('shop.hook.'
            . HOOK_ARTIKEL_CLASS_FUELLEARTIKEL, [$this->sales, 'fuelleArtikel']);
        $dispatcher->listen('shop.hook.'
            . HOOK_SHOP_SET_PAGE_TYPE, [$this->sales, 'applyCoupon']);
    }

    public function renderAdminMenuTab(string $tabName, int $menuID, JTLSmarty $smarty): string
    {
        $plugin      = $this->getPlugin();
        $db          = $this->getDB();
        $this->sales = new Sales(
            $plugin,
            $db
        );
        // @phpstan-ignore-next-line APPLICATION_VERSION is provided by JTL Shop at runtime
        $isShop52 = (int)\str_replace('.', '', APPLICATION_VERSION) >= 520;
        $url      = Shop::getURL();
        $kuponurl = ($isShop52) ? 'coupons' : 'kupons.php';
        $smarty->assign('plugin_pfad', $url . '/plugins/tnt_coupons/');
        $smarty->assign('admin_pfad', $url . '/admin/');
        $smarty->assign('coupons_pfad', $url . '/admin/' . $kuponurl);

        $css_additional = '<link rel="stylesheet" media="screen" href="' . Shop::getURL()
            . '/plugins/tnt_coupons/adminmenu/vendor/simplebar/dist/simplebar.min.css"/>';
        $js_additional  = '<script src="' . Shop::getURL()
            . '/plugins/tnt_coupons/adminmenu/vendor/bootstrap/dist/js/bootstrap.bundle.min.js"></script>'
            . '<script src="' . Shop::getURL()
            . '/plugins/tnt_coupons/adminmenu/vendor/simplebar/dist/simplebar.min.js"></script>'
            . '<script src="' . Shop::getURL()
            . '/plugins/tnt_coupons/adminmenu/vendor/smooth-scroll/dist/smooth-scroll.polyfills.min.js"></script>';

        $smarty->assign('css_additional', $css_additional);
        $smarty->assign('js_additional', $js_additional);

        if ($tabName === 'Support / Anfragen') {
            $tpl_path = rtrim($this->getPlugin()->getPaths()->getAdminPath(), '/');
            return $smarty->fetch($tpl_path . '/templates/backoffice.tpl');
        }

        //$dbObj = $db->selectSingleRow("tnt_coupons_config", "cTemplate", "coupons");
        if (!empty($_POST['tnt_sale_kupon'])) {
            $kkupon = (int)$_POST['tnt_sale_kupon'];
            if ($kkupon > 0) {
                $files    = $_FILES;
                $sale_img = '';
                foreach ($files as $k => $v) {
                    if (
                        $k === 'tnt_cp_file'
                        && isset($v['size'])
                        && $v['size'] > 0
                        && !empty($v['tmp_name'])
                        && !empty($v['type'])
                    ) {
                        $ext = '';
                        switch ($v['type']) {
                            case 'image/png':
                                $ext = '.png';
                                break;
                            case 'image/gif':
                                $ext = '.gif';
                                break;
                            case 'image/jpeg':
                                $ext = '.jpg';
                                break;
                            case 'image/webp':
                                $ext = '.webp';
                                break;
                        }
                        if ($ext !== '') {
                            $paths    = $this->getPlugin()->getPaths();
                            $imageDir = $paths->getBasePath() . 'images/';
                            $sale_img = $paths->getBaseUrl() . 'images/sale_' . $kkupon . $ext;

                            if (!\is_dir($imageDir) && !mkdir($imageDir, 0755) && !is_dir($imageDir)) {
                                throw new \RuntimeException(
                                    'Error creating the tnt_coupons image directory.'
                                );
                            }

                            \move_uploaded_file(
                                $v['tmp_name'],
                                $imageDir . 'sale_' . $kkupon . $ext
                            );
                        }
                    }
                }
                unset($_POST['tnt_sale_kupon']);
                if (!empty($sale_img)) {
                    $_POST['tnt_cp_file'] = $sale_img;
                }
                $obj         = new stdClass();
                $obj->tkey   = 'kupon';
                $obj->tvalue = $kkupon;
                $obj->textra = \json_encode($_POST);
                $db->updateRow('tnt_coupons_config', ['tkey', 'tvalue'], ['kupon', $kkupon], $obj);
            }
        }

        $template = 'einstellungen.tpl';

        $allCoupons = $this->sales->getCoupons(true);
        $coupons    = ['active' => [], 'upcoming' => [], 'past' => []];
        $now        = new DateTimeImmutable();
        foreach ($allCoupons as $cp) {
            $details     = $this->sales->convertToSale($cp, false, 3);
            $adminCoupon = $this->buildAdminCoupon($cp, $details);
            $validFrom   = \date_create_immutable($cp->dGueltigAb);
            if ($validFrom instanceof DateTimeImmutable && $validFrom > $now) {
                $coupons['upcoming'][] = $adminCoupon;
            } elseif ($cp->cAktiv === 'Y') {
                $coupons['active'][] = $adminCoupon;
            } else {
                $coupons['past'][] = $adminCoupon;
            }
        }
        $smarty->assign(
            'allCPs',
            $coupons
        );
        $adminLang = (string)($_SESSION['AdminAccount']->language ?? 'de-DE');
        $english   = WeekdayLabels::isEnglish($adminLang);
        $smarty->assign('tnt_cp_weekdays', WeekdayLabels::days($english))
            ->assign('tnt_cp_weekday_heading', WeekdayLabels::heading($english))
            ->assign('tnt_cp_weekday_help', WeekdayLabels::help($english));
        $tpl_path = rtrim($this->getPlugin()->getPaths()->getAdminPath(), '/');

        return $smarty->fetch($tpl_path . '/templates/' . $template);
    }
}
