<?php

namespace YSquare\GiftCert\Core;

use OxidEsales\Eshop\Application\Model\Article;
use OxidEsales\Eshop\Core\Field;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;

class GiftCertHandler
{
    // What to handle?
    // - get Certs for an order
    // - send certs by email (plain or PDF attached)
    // - get all certs not yet send and overdue
    // - produce PDF Certs


    protected $_iVoucherLength = "8";
    protected $_sVoucherChars = "0123456789abcdefghijklmnopqrstuvwxyz";
    protected $_pdfFilePath;

    /**
     * GiftCertHandler constructor.
     */
    function __construct()
    {
        $config = Registry::getConfig();
        $length = trim($config->getConfigParam('sYsGiftcertLength'));
        $allowedCahrs = trim($config->getConfigParam('sYsGiftcertAllowedChars'));
        if ($length !== "" && is_numeric($length)) {
            $this->_iVoucherLength = $length;
        }

        if ($allowedCahrs !== "") {
            $this->_sVoucherChars = $allowedCahrs;
        }

        $this->_pdfFilePath = Registry::getConfig()->getConfigParam("sShopDir") . "tmp/";
    }

    /**
     * @param $oArticle
     * @param $dPrice
     * @param null $options
     */
    function generateGiftCert($oArticle, $dPrice, $user = null, $orderId = "", $options = null)
    {
        $deliveryOption = $oArticle->isOfflineGiftCert() ? 1 : 0; // 0 = email, 1 = offline
        $deliveryDate = date("Y-m-d"); // default is today
        $purchaserMail = "";
        $recipientMail = "";
        $recipientText = "";

        if ($user) {
            $purchaserMail = $user->oxuser__oxusername->value;
        }

        if (null !== $options) {

            if (isset($options["deliveryOption"])) {
                // if there is a setting from outside that this giftcert should be mailed
                // well then, we do this
                $deliveryOption = $options["deliveryOption"];
            }
            if (isset($options["preferredSendDate"])) {
                $deliveryDate = $options["preferredSendDate"];
            }
            if (isset($options["recipientMail"])) {
                $recipientMail = $options["recipientMail"];
            }
            if (isset($options["messageToRecipient"])) {
                $recipientText = $options["messageToRecipient"];
            }
            if (isset($options["originArticleId"])) {
                $originArticleId = $options["originArticleId"];
            }

        }

        $individualOptions = [
            'purchaserMail'   => $purchaserMail,
            'recipientMail'   => $recipientMail,
            'recipientText'   => $recipientText,
            'originArticleId' => $originArticleId,
        ];
        if ($oArticle->isGiftCertArticle() && $dPrice > 0) {
            $sCode = $this->_generateGiftCertCode();
            $oGiftcert = oxNew(\YSquare\GiftCert\Model\GiftCert::class);
            $oGiftcert->ysgiftcert__ysgiftcertnr = new Field($sCode);
            $oGiftcert->ysgiftcert__ysinitialdiscount = new Field($dPrice);
            $oGiftcert->ysgiftcert__ysrestdiscount = new Field($dPrice);
            $oGiftcert->ysgiftcert__ysdatepurchased = new Field(date('Y-m-d H:i:s'));
            $oGiftcert->ysgiftcert__ysdeliveryoption = new Field($deliveryOption);
            $oGiftcert->ysgiftcert__ysdeliverydate = new Field($deliveryDate);
            $oGiftcert->ysgiftcert__ysindividualoptions = new Field(json_encode($individualOptions));
            $oGiftcert->ysgiftcert__oxorderid = new Field($orderId);
            $oGiftcert->save();
        }

        return $oGiftcert;


    }

    /**
     * Generates the actual code of the cert
     *
     * @return string
     */
    protected function _generateGiftCertCode()
    {
        $string = '';
        for ($p = 0; $p < $this->_iVoucherLength; $p++) {
            $string .= $this->_sVoucherChars[mt_rand(0, strlen($this->_sVoucherChars) - 1)];
        }

        $prefix = Registry::getConfig()->getConfigParam('aYsGiftcertPrefix');
        $string = $prefix . "-" . $string;

        return $string;
    }

    /**
     * @param $giftcert Giftcert Object that holds the setup
     * @param $sImage Image that should be used as background (old style - better use 12th picture in article
     * @param $output Output Type for PDF (F = as file e.g. for attachment, D = direct download in Browser e.g. for testing)
     * @param $template Different Template file (currently not in use)
     * @return string
     */
    public function generateAttachmentPDF($giftcert, $sImage = '', $output = 'F', $template = null)
    {
        $logger = Registry::getLogger();
        $filename = $this->_pdfFilePath . uniqid(rand(), true) . '.pdf';
        $config = Registry::getConfig();
        $currency = $config->getActShopCurrencyObject();

        // Check which image to use as background the given one (that is located in module directory - maybe deprecated -
        // or the 12th product image of the used article, or TODO: a template file
        if ($sImage !== '') {
            $imageFullPath =
                Registry::getConfig()->getConfigParam("sShopDir") .
                'modules/ysquare/ys_giftcert/out/img/' . $sImage;
            $imageDiv = "<div><img src='" . $imageFullPath . "' style='width:100%'></div>";
            $logger->error("Image");
        } else {
            $params = json_decode($giftcert->ysgiftcert__ysindividualoptions->rawValue, true);
            $logger->error("No Image",[$params]);
            $article = oxNew(Article::class);
            if ($article->load($params["originArticleId"])) {
                $imageFullPath =
                    Registry::getConfig()->getConfigParam("sShopDir") .
                    'out/pictures/master/product/12/' . $article->oxarticles__oxpic12->value;
            }
        }
        $imageFullPath_extension = pathinfo($imageFullPath);
        $imageFullPath_extension = $imageFullPath_extension["extension"];

        // Setup Fonts
        $defaultConfig = (new \Mpdf\Config\ConfigVariables())->getDefaults();
        $fontDirs = $defaultConfig['fontDir'];
        $defaultFontConfig = (new \Mpdf\Config\FontVariables())->getDefaults();
        $fontData = $defaultFontConfig['fontdata'];

        $fontDirs = array_merge($fontDirs, [
            __DIR__ . "/../out/fonts/Barlow_Semi_Condensed",
            __DIR__ . "/../out/fonts/Oswald/static",
        ]);
        $fontData = $fontData + [
                'barlowbold'   => [
                    'R' => 'BarlowSemiCondensed-Bold.ttf',
                    'I' => 'BarlowSemiCondensed-BoldItalic.ttf',
                ],
                'barlowregular' => [
                    'R' => 'BarlowSemiCondensed-Regular.ttf',
                    'I' => 'BarlowSemiCondensed-MediumItalic.ttf',
                ],
                'oswaldregular'       => [
                    'R' => 'Oswald-Regular.ttf',
                ],
                'oswaldsemibold'       => [
                    'R' => 'Oswald-SemiBold.ttf',
                ],
            ];

        $mpdf = new \Mpdf\Mpdf([
            'fontDir' => $fontDirs,
            'fontdata' => $fontData,
            'default_font' => 'barlowregular'
        ]);

        // Choose weather to load a pdf as template or use an image as background
        if ($imageFullPath_extension == "jpg" || $imageFullPath_extension == "png") {
            $imageDiv = "<div><img src='" . $imageFullPath . "' style='width:100%'></div>";
        } elseif ($imageFullPath_extension == "pdf") {
            $imageDiv = "";
            $pagecount = $mpdf->setSourceFile($imageFullPath);
            $tplIdx = $mpdf->importPage($pagecount);
            $mpdf->useTemplate($tplIdx);
        }

        $params["imageDiv"] = $imageDiv;
        $params["currencySign"] = $currency->sign;

        $mpdf->writeHtml($this->renderGiftcertTemplate($params,$giftcert));

        // outputting file to browser
        $mpdf->output($filename, $output);

        return $filename;
    }

    protected function renderGiftcertTemplate($params, $giftcert)
    {
        $renderer = oxNew(\OxidEsales\Eshop\Application\Model\SmartyRenderer::class);
        $aViewData = [
            "params"       => $params,
            "giftcert"     => $giftcert
        ];

        return $renderer->renderTemplate("giftcert/default.tpl", $aViewData);
    }


    public function generatePrintPDF($giftcert)
    {

    }

    /**
     * Some payment Modules call the voucher redeem Process twice.
     * This function checks if the pool was already used for this order
     *
     * @param $orderid
     */
    public function isPoolRedeemedInOrder($orderid)
    {
        $container = ContainerFactory::getInstance()->getContainer();
        $queryBuilderFactory = $container->get(QueryBuilderFactoryInterface::class);


        $queryBuilder = $queryBuilderFactory->create();
        $queryBuilder
            ->select("count(*) as cnt")
            ->from("ysgiftcertlog")
            ->where("ysorderid = :ysorderid")
            ->andWhere("yspoolredeem = 1")
            ->setParameter("ysorderid", $orderid);
        $blocksData = $queryBuilder->execute();
        $blocksData = $blocksData->fetchAll();

        if ($blocksData[0]['cnt'] > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Some payment modules call the voucher redeem process twice.
     * This function checks if the given giftcert was already used for this order
     *
     * @param $giftcertid
     * @param $orderid
     * @return bool
     */
    public function isGiftCertRedeemedInOrder($giftcertid, $orderid) {
        $container = ContainerFactory::getInstance()->getContainer();
        $queryBuilderFactory = $container->get(QueryBuilderFactoryInterface::class);


        $queryBuilder = $queryBuilderFactory->create();
        $queryBuilder
            ->select("count(*) as cnt")
            ->from("ysgiftcertlog")
            ->where("ysorderid = :ysorderid")
            ->andWhere("ysgiftcertid = :ysgiftcertid")
            ->setParameters(["ysorderid" => $orderid,"ysgiftcertid" => $giftcertid]);
        $blocksData = $queryBuilder->execute();
        $blocksData = $blocksData->fetchAll();

        if ($blocksData[0]['cnt'] > 0) {
            return true;
        } else {
            return false;
        }
    }

    public function logPoolRedeem($orderid, $userid, $valueRedeemed)
    {
        // add log entry for purchase
        $giftcertLog = oxNew(\YSquare\GiftCert\Model\GiftCertLog::class);
        $giftcertLog->ysgiftcertlog__ysgiftcertid = new Field('-');
        $giftcertLog->ysgiftcertlog__yspoolredeem = new Field(1);
        $giftcertLog->ysgiftcertlog__ysamountused = new Field($valueRedeemed);
        $giftcertLog->ysgiftcertlog__ysorderid = new Field($orderid);
        $giftcertLog->ysgiftcertlog__ysuserid = new Field($userid);
        $giftcertLog->ysgiftcertlog__ysdateused = new Field(date("Y-m-d H:i:s", Registry::getUtilsDate()->getTime()));
        $giftcertLog->save();
    }
}