<?php
/**
 * 2007-2023 PrestaShop
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 *
 *  @author    PrestaShop SA <contact@prestashop.com>
 *  @copyright 2007-2023 PrestaShop SA
 *  @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 *  International Registered Trademark & Property of PrestaShop SA
 */

namespace PrestaShop\Module\AgileMultisellerPro\Helper;

use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoMembershipCustomer;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoMembershipType;
use PrestaShop\Module\AgileMultisellerPro\Form\Configuration\Membership\DataConfiguration as MembershipDataConfiguration;
use PrestaShop\Module\AgileMultisellerPro\Helper\Email\AgileMailer;

if (!defined('_PS_VERSION_')) {
    exit;
}

class AgileHelperMembership extends \PaymentModule
{
    public $active = true;
    public $name = 'agilemembership';
    private static $entityManager;

    private static function getEntityManager()
    {
        if (empty(self::$entityManager)) {
            self::$entityManager = AgileHelper::buildContainer()->get('doctrine.orm.entity_manager');
        }

        return self::$entityManager;
    }

    public static function isProductInMembershipCategory($id_product)
    {
        $sql = 'SELECT `id_category`
            FROM `' . _DB_PREFIX_ . 'category_product`
            WHERE `id_category`=' . (int) \Configuration::get('AGILE_MEMBERSHIP_CID') . '
                AND id_product =' . (int) $id_product;

        $result = \Db::getInstance()->getRow($sql);

        if (isset($result['id_category']) && (int) $result['id_category'] > 0) {
            return true;
        }

        return false;
    }

    public static function assignMembership($customer, $id_product, $id_order_Status)
    {
        $context = \Context::getContext();
        $newcart = self::createnewcart($customer, $id_product);

        $carttotal = $newcart->getOrderTotal();

        $customer_cart_id = $context->cart->id;
        $pmodule = new self();

        if ($id_order_Status == 0) {
            $id_order_Status = _PS_OS_PAYMENT_;
        }

        $pmodule->validateOrder(
            $newcart->id,
            $id_order_Status,
            $carttotal,
            $pmodule->name,
            'Free Trial',
            [],
            null,
            false,
            $customer->secure_key
        );

        $context->cart = new \Cart($customer_cart_id);

        return $pmodule->currentOrder;
    }

    public static function createnewcart($customer, $id_product)
    {
        $context = \Context::getContext();
        $id_address = \Address::getFirstCustomerAddressId($customer->id);

        $newcart = new \Cart();
        $newcart->id_customer = $customer->id;
        $newcart->id_lang = $context->cookie->id_lang;
        $newcart->id_carrier = 0;
        $newcart->id_address_delivery = $id_address;
        $newcart->id_address_invoice = $id_address;

        if ($context->cookie->id_currency > 0) {
            $newcart->id_currency = $context->cookie->id_currency;
        } else {
            $newcart->id_currency = (int) \Configuration::get('PS_CURRENCY_DEFAULT');
        }

        $newcart->id_guest = 0;
        $newcart->recyclable = 0;
        $newcart->gift = 0;
        $newcart->gift_message = '';

        $newcart->add();

        $sql = 'INSERT INTO `' . _DB_PREFIX_ . 'cart_product` (id_cart,id_product,id_product_attribute,quantity,date_add) VALUES (' . $newcart->id . ',' . $id_product . ',0,1,\'' . date('Y-m-d H:i:s') . '\')';
        \Db::getInstance()->Execute($sql);

        return $newcart;
    }

    public static function createFreeMembership($customer)
    {
        if (\Configuration::get(MembershipDataConfiguration::AGILE_MEMBERSHIP_STATUS)) {
            $id_membership_type = (int) \Configuration::get(MembershipDataConfiguration::AGILE_MEMBERSHIP_FREE_TRIAL_ID);

            if ($id_membership_type <= 0) {
                return;
            }

            $sellerinfoMembershipType = self::getEntityManager()->getRepository(SellerinfoMembershipType::class)
                ->find($id_membership_type);

            if ($sellerinfoMembershipType) {
                self::assignMembership(
                    $customer,
                    $sellerinfoMembershipType->getIdProduct(),
                    (int) \Configuration::get('AGILE_MEMBERSHIP_FREE_TRIAL_STATE')
                );
            }
        }
    }

    public static function showFreeMembershipEligibility($params)
    {
        $donoteligibles = [];
        $context = \Context::getContext();

        $sellerInfoMembershipCustomerRepository = self::getEntityManager()->getRepository(SellerinfoMembershipCustomer::class);

        foreach ($context->cart->getProducts() as $product) {
            if ($product['price'] != 0) {
                continue;
            }

            if (!self::isProductInMembershipCategory((int) $product['id_product'])) {
                continue;
            }

            if ($sellerInfoMembershipCustomerRepository->hasUsedBefore($product['id_product'], $context->cart->id_customer)) {
                continue;
            }

            $donoteligibles[] = $product['name'];
        }

        if (count($donoteligibles) <= 0) {
            return null;
        }

        $context->smarty->assign([
            'donoteligibles' => $donoteligibles,
            'donoteligibles_nb' => count($donoteligibles),
        ]);

        return $context->smarty->fetch(
            'module:agilemultisellerpro/views/templates/hook/hookshoppingcart.tpl'
        );
    }

    public static function sendMembershipExiprationReminder()
    {
        $context = \Context::getContext();

        $settings = \Configuration::get('AGILE_MEMBERSHIP_REMINDER_DAYS');

        if (!isset($settings) || empty($settings)) {
            return;
        }

        $reminder_days = explode(',', $settings);
        if (!isset($reminder_days) || empty($reminder_days)) {
            return;
        }

        $criteria = '';
        foreach ($reminder_days as $days) {
            if ((int) $days <= 0) {
                continue;
            }
            if (!empty($criteria)) {
                $criteria .= ' OR ';
            }
            $criteria .= '(
                DATE_ADD( CURDATE( ) , INTERVAL ' . (int) $days . ' DAY ) > mmh.max_expiry_date
                AND
                (a.reminder_email_date IS NULL OR DATE_ADD(a.reminder_email_date, INTERVAL ' . (int) $days . ' DAY)< mmh.max_expiry_date)
               )';
        }

        $sql = 'SELECT distinct a.id_customer
                ,c.lastname
                ,c.firstname
                ,c.email
                ,mmh.max_expiry_date, IFNULL(DATEDIFF(mmh.max_expiry_date, CURDATE( ) ),0) AS days_to_expire
                ,o.id_lang
                ,a.reminder_email_date
                FROM `' . _DB_PREFIX_ . 'sellerinfo_membership_customer` a
                INNER JOIN
                    (
                        SELECT cm1.id_customer,max(mh1.expiry_date) as max_expiry_date
                        FROM `' . _DB_PREFIX_ . 'sellerinfo_membership_customer` cm1
                        LEFT JOIN `' . _DB_PREFIX_ . 'sellerinfo_membership_history` mh1 ON (cm1.id_customer = mh1.id_customer AND IFNULL(mh1.is_cancelled,0) = 0)
                        Group BY cm1.id_customer
                    ) mmh ON a.id_customer = mmh.id_customer
                ' . AgileHelperMembership::joinTables($context->cookie->id_lang) . '
                WHERE c.active=1 AND a.activated=1 AND mmh.max_expiry_date IS NOT NULL AND IFNULL(mh.is_cancelled,0) = 0
                AND (' . $criteria . ')
                ORDER BY days_to_expire ASC
                LIMIT 0,10';

        $results = \Db::getInstance()->executeS($sql);

        if (empty($results)) {
            return;
        }

        $shop = new \Shop(\Configuration::get('PS_SHOP_DEFAULT'));

        foreach ($results as $customer) {
            $data = [
                '{firstname}' => $customer['firstname'],
                '{lastname}' => $customer['lastname'],
                '{email}' => $customer['email'],
                '{shop_name}' => \Configuration::get('PS_SHOP_NAME'),
                '{shop_url}' => $shop->getBaseURL(),
                '{shop_logo}' => $shop->getBaseURL() . 'img/logo.jpg',
                '{days_to_expire}' => $customer['days_to_expire'],
            ];

            $id_lang = (int) $customer['id_lang'];
            if (!$id_lang) {
                $id_lang = \Configuration::get('PS_LANG_DEFAULT');
            }

            $iso = \Language::getIsoById($id_lang);

            if (file_exists(_PS_MODULE_DIR_ . 'agilemultisellerpro/mails/' . $iso . '/expiration_reminder.txt')
                && file_exists(_PS_MODULE_DIR_ . 'agilemultisellerpro/mails/' . $iso . '/expiration_reminder.html')
            ) {
                AgileMailer::SendTranslateSubject(
                    $id_lang,
                    'expiration_reminder',
                    $data,
                    $customer['email'],
                    $customer['firstname'] . ' ' . $customer['lastname'],
                    null,
                    null,
                    null,
                    null,
                    dirname(__FILE__) . '/mails/'
                );

                $sql = 'UPDATE `' . _DB_PREFIX_ . 'sellerinfo_membership_customer`  SET reminder_email_date=CURDATE() WHERE id_customer=' . (int) $customer['id_customer'];
                \Db::getInstance()->execute($sql);
            }
        }
    }

    public static function joinTables($id_lang)
    {
        $context = \Context::getContext();
        if (!isset($id_lang) || (int) $id_lang <= 0) {
            $id_lang = $context->language->id;
        }

        return '
                LEFT JOIN `' . _DB_PREFIX_ . 'customer` c ON a.id_customer=c.id_customer
                LEFT JOIN `' . _DB_PREFIX_ . 'sellerinfo_membership_history` mh ON c.id_customer = mh.id_customer
                LEFT JOIN `' . _DB_PREFIX_ . 'order_detail` od ON (mh.id_order = od.id_order AND mh.id_product = od.product_id AND mh.id_product_attribute = od.product_attribute_id)
                LEFT JOIN `' . _DB_PREFIX_ . 'order_state_lang` osl ON (mh.id_order_state=osl.id_order_state AND osl.id_lang=' . $id_lang . ')
                LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (mh.id_product=pl.id_product AND pl.`id_lang` = ' . (int) $id_lang . (_PS_VERSION_ < 1.5 ? '' : ' AND pl.id_shop=' . (int) \Configuration::get('PS_SHOP_DEFAULT')) . ')
                LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON od.id_order = o.id_order
                ';
    }

    public static function isMemberOnlyContent($sellerinfo)
    {
        if (\Configuration::get(MembershipDataConfiguration::AGILE_MEMBERSHIP_STATUS)) {
            $context = \Context::getContext();

            switch ($context->controller->php_self) {
                case 'category':
                    return self::isMemberOnlyContentCategory($sellerinfo);
                case 'product':
                    return self::isMemberOnlyContentProduct($sellerinfo);
                case 'cart':
                case 'order':
                    return self::isMemberOnlyCart($sellerinfo, $context);
            }
        }

        return false;
    }

    public static function isMemberOnlyContentCategory($sellerinfo)
    {
        if (
            \Tools::getValue('id_category') == \Configuration::get(MembershipDataConfiguration::AGILE_MEMBERSHIP_CID)
            && !self::isSeller($sellerinfo)
        ) {
            return true;
        }

        return false;
    }

    public static function isMemberOnlyContentProduct($sellerinfo)
    {
        if (
            self::isProductInMembershipCategory((int) \Tools::getValue('id_product'))
            && !self::isSeller($sellerinfo)
        ) {
            return true;
        }

        return false;
    }

    public static function isMemberOnlyCart($sellerinfo, $context)
    {
        if (!self::isSeller($sellerinfo)) {
            foreach ($context->cart->getProducts() as $product) {
                if (self::isProductInMembershipCategory((int) $product['id_product'])) {
                    return true;
                }
            }
        }

        return false;
    }

    private static function isSeller($sellerinfo): bool
    {
        if (
            $sellerinfo
            && $sellerinfo->getIdSellerinfo()
        ) {
            return true;
        }

        return false;
    }

    public static function hideProducts($date)
    {
        if (\Configuration::get(MembershipDataConfiguration::AGILE_MEMBERSHIP_STATUS)) {
            if (!$date) {
                $date = date('Y-m-d H:i:s', time());
            }

            $idsSeller = self::getIdsSellerExpiredMembership($date);

            if ($idsSeller) {
                $idsSeller = implode(', ', $idsSeller);

                $sql = 'UPDATE `' . _DB_PREFIX_ . 'product` p
                    SET p.`active` = 0
                    WHERE p.`id_product` = (SELECT sip.`id_product`
                        FROM `' . _DB_PREFIX_ . 'sellerinfo_product` sip
                        WHERE sip.`id_product` = p.`id_product`
                            AND sip.`id_sellerinfo` IN (' . pSQL($idsSeller) . ')
                    )
                ';
                \Db::getInstance()->execute($sql);

                $sql = 'UPDATE `' . _DB_PREFIX_ . 'product_shop` ps
                    SET ps.`active` = 0
                    WHERE ps.`id_product` = (SELECT sip.`id_product`
                        FROM `' . _DB_PREFIX_ . 'sellerinfo_product` sip
                        WHERE sip.`id_product` = ps.`id_product`
                            AND sip.`id_sellerinfo` IN (' . pSQL($idsSeller) . ')
                    )
                ';
                \Db::getInstance()->execute($sql);
            }
        }
    }

    private static function getIdsSellerExpiredMembership($expiryDate)
    {
        $sql = ' SELECT s.id_sellerinfo
            FROM `' . _DB_PREFIX_ . 'sellerinfo` s
                LEFT JOIN `' . _DB_PREFIX_ . 'sellerinfo_membership_history` smh ON (
                    smh.id_customer = s.id_customer AND smh.expiry_date >= "' . pSQL($expiryDate) . '"
                    AND smh.id_order_state != 6
                    AND IFNULL(smh.is_cancelled, 0) != 1
                )
                WHERE smh.id_membership_history IS NULL
                GROUP BY s.id_sellerinfo
                ORDER BY smh.expiry_date DESC;';

        $result = \Db::getInstance()->ExecuteS($sql);

        return array_column($result, 'id_sellerinfo');
    }

    public static function getProductsByCart($idCart)
    {
        return \Db::getInstance()->ExecuteS('SELECT `id_product`, `id_product_attribute`
            FROM `' . _DB_PREFIX_ . 'cart_product` WHERE `id_cart` = ' . (int) $idCart);
    }
}
