<?php

namespace YSquare\GiftCert\Cron;

use OxidEsales\Eshop\Application\Model\Article;
use OxidEsales\Eshop\Application\Model\Order;
use OxidEsales\Eshop\Core\Email;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
use YSquare\GiftCert\Core\GiftCertHandler;
use YSquare\GiftCert\Model\GiftCert;

class GiftCertJobs
{

    /**
     * @var mixed
     */
    protected $queryBuilderFactory;

    /**
     * GiftCertHandler constructor.
     */
    public function __construct()
    {
        $container = ContainerFactory::getInstance()->getContainer();
        $this->queryBuilderFactory = $container->get(QueryBuilderFactoryInterface::class);
    }

    /**
     *
     */
    public function sendGiftcerts()
    {
        $logger = Registry::getLogger();

        // Load Settings
        $daysBeforeDeletion = Registry::getConfig()->getConfigParam('iYsGiftcertKeepBrokenOrdersInDays');
        $daysBeforeDeletion = is_numeric($daysBeforeDeletion) ? intval($daysBeforeDeletion) : 3;
        $acceptedOrderStates = array_map('strtolower',
            Registry::getConfig()->getConfigParam('aYsGiftcertPaymentSuccessfulStates') ?: []
        );

        $queryBuilder = $this->queryBuilderFactory->create();
        $queryBuilder
            ->select('*')
            ->from("ysgiftcert")
            ->where('ysdelivered = 0')
            ->andWhere('ysdeliverydate <= :deliverydate')
            ->setParameter("deliverydate", date("Y-m-d"));

        $blocksData = $queryBuilder->execute();
        $blocksData = $blocksData->fetchAll();

        foreach ($blocksData as $entry) {
            $giftcert = oxNew(GiftCert::class);
            if ($giftcert->load($entry["OXID"])) {
                $options = json_decode($entry["YSINDIVIDUALOPTIONS"], true);

                // If individual Options are empty this giftcert should be delivered to the order owner
                // or not at all (because it already should have been delivered)? TODO: check for the behaviour
                if (trim($entry["YSINDIVIDUALOPTIONS"]) == "" || !isset($options["recipientMail"]) || trim($options["recipientMail"]) == "") {
                    $giftcert->markAsDelivered();
                    continue;
                }

                // If this is a business giftcert it should never be send by email
                if (isset($options["isBusinessGiftcert"]) && $options["isBusinessGiftcert"] = 1) {
                    $giftcert->markAsDelivered();
                    continue;
                }

                // load order info
                // TODO: Certs where the orders got deleted will not be deleted here as the order cannot be loaded (Maybe other Feature)
                $order = oxNew(Order::class);
                if (trim($giftcert->ysgiftcert__oxorderid->value) !== "") {
                    if ($certFromOrder = $order->load($giftcert->ysgiftcert__oxorderid->value)) {
                        $shopid = $order->oxorder__oxshopid->value;
                        $langid = $order->oxorder__oxlang->value;
                        $purchaserFirstName = $order->oxorder__oxbillfname->value;
                        $purchaserLastName = $order->oxorder__oxbilllname->value;
                        $orderStatus = $order->oxorder__oxtransstatus->value;
                        $orderDate = new \DateTime($order->oxorder__oxorderdate->value);
                    } else {
                        // if order was deleted we no longer plan to send the giftcert as this normally happens
                        // if the order was not completed or not completely paid
                        $giftcert->markAsDelivered();
                        continue;
                    }
                }

                // If order status not ok, the order was not paid yet, so we do not send the giftcert
                $paid = in_array(strtolower($orderStatus), $acceptedOrderStates);
                if($certFromOrder && $paid) {
                    // If order is not ok and some time old, we remove the giftcert completely
                    $currentDate = new \DateTime();
                    $interval = $currentDate->diff($orderDate);

                    $logger->error('This giftcert is invalid due to not paid order: ' . $entry["YSGIFTCERTNR"] . " // ". $order->oxorder__oxordernr->value . " // " . $interval->days ." of ".$daysBeforeDeletion, [__CLASS__, __FUNCTION__]);

                    if($interval->invert && $interval->days >= $daysBeforeDeletion){
                        $logger->error('- Order still not paid after threshold. Deleting the giftcert. ' , [__CLASS__, __FUNCTION__]);
                        $giftcert->delete();
                    }
                    continue;
                }

                // Produce the PDF
                $giftcertHandler = oxNew(GiftCertHandler::class);

                $filesToAttach = [];
                $filesToAttach[] = $giftcertHandler->generateAttachmentPDF($giftcert);

                $giftcert->markAsDelivered();

                // Send eMail to Recipient
                $email = oxNew(Email::class);
                $email->sendGiftcertEmailToRecipient($giftcert, $filesToAttach, $langid, $shopid, $purchaserFirstName, $purchaserLastName);
                // Send eMail to order owner
                $email = oxNew(Email::class);
                $email->sendGiftcertEmailToPurchaser($giftcert, $filesToAttach, $langid, $shopid);
                // Send eMail to shop owner
                $email = oxNew(Email::class);
                $email->sendGiftcertEmailToShopOwner($giftcert, $filesToAttach, $langid, $shopid);

                //delete files
                foreach ($filesToAttach as $file) {
                    unlink($file);
                }
            }
        }
    }
}
