<?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\SellerinfoCommissionBase;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoCommissionRate;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoMembershipType;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoRatingCriterion;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoRatingCriterionLang;
use PrestaShop\Module\AgileMultisellerPro\Form\Configuration\Commissions\DataConfiguration as CommissionsDataConfiguration;
use PrestaShop\Module\AgileMultisellerPro\Form\Configuration\Membership\DataConfiguration as MembershipDataConfiguration;
use PrestaShopBundle\Entity\Lang;

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

class AgileInstall
{
    private $module;
    private $entityManager;
    private $translator;

    private $trialMembershipTypeId = 0;

    public function __construct($module)
    {
        $this->module = $module;
        $this->entityManager = AgileHelper::buildContainer()->get('doctrine.orm.entity_manager');
        $this->translator = \Context::getContext()->getTranslator();
    }

    public function processInstall()
    {
        return
            $this->registerTabs()
            && $this->registerHooks()
            && $this->prepareDefaultCommissionBase()
            && $this->prepareDefaultCommissionRate()
            && $this->initCriterions()
            && $this->setMembershipCategory()
            && $this->setDefaultConfiguration()
        ;
    }

    private function registerHooks()
    {
        return
            $this->module->registerHook('displayHeader')
            && $this->module->registerHook('displayFooter')
            && $this->module->registerHook('actionFrontControllerSetMedia')
            && $this->module->registerHook('actionOrderStatusUpdate')
            && $this->module->registerHook('actionValidateOrder')
            && $this->module->registerHook('displayTop')
            && $this->module->registerHook('displayCustomerAccount')
            && $this->module->registerHook('displayContentWrapperBottom')
            && $this->module->registerHook('displayBeforeCarrier')
            && $this->module->registerHook('displayMyAccountBlock')
            && $this->module->registerHook('displayRightColumnProduct')
            && $this->module->registerHook('displayProductExtraContent')
            && $this->module->registerHook('displayProductAdditionalInfo')
            && $this->module->registerHook('moduleRoutes')
            && $this->module->registerHook('displayOrderCarriersList')
            && $this->module->registerHook('displayOverrideTemplate')
            && $this->module->registerHook('actionEmailSendBefore')
            && $this->module->registerHook('actionCustomerAccountAdd')
            && $this->module->registerHook('displayShoppingCartFooter')
            && $this->module->registerHook('actionCartSave')

            // ps 8.1.x
            && $this->module->registerHook('actionProductGridDefinitionModifier')
            && $this->module->registerHook('actionProductGridQueryBuilderModifier')

            // ps 8.0.x
            && $this->module->registerHook('adminCatalogSellersList')
            && $this->module->registerHook('actionAdminProductsListingFieldsModifier')

            && $this->module->registerHook('actionObjectOrderDetailDeleteAfter')
            && $this->module->registerHook('actionObjectProductAddAfter')
            && $this->module->registerHook('actionObjectProductUpdateAfter')
            && $this->module->registerHook('actionObjectProductDeleteAfter')
        ;
    }

    private function registerTabs()
    {
        $tabs = [
            [
                'className' => 'AdminAgileModulesParent',
                'tabName' => 'Agile Modules',
                'routeName' => false,
                'parentClassName' => '',
                'isActive' => true,
            ],
        ];

        $multipleSellerTabs = [
            [
                'className' => 'MultipleSellersParent',
                'tabName' => 'Multiple Seller',
                'routeName' => false,
                'parentClassName' => 'AdminAgileModulesParent',
                'isActive' => true,
            ],
            [
                'className' => 'AdminSellerInfos',
                'tabName' => 'Seller Business Info',
                'routeName' => 'admin_agile_seller_infos',
                'parentClassName' => 'MultipleSellersParent',
                'isActive' => true,
            ],
            [
                'className' => 'AdminOrderProducts',
                'tabName' => 'Purchased Products',
                'routeName' => 'admin_agile_order_products',
                'parentClassName' => 'MultipleSellersParent',
                'isActive' => true,
            ],
            [
                'className' => 'AdminSellerCategories',
                'tabName' => 'Seller Categories',
                'routeName' => 'admin_agile_seller_categories',
                'parentClassName' => 'MultipleSellersParent',
                'isActive' => true,
            ],
            [
                'className' => 'AdminSellerRatings',
                'tabName' => 'Seller Ratings',
                'routeName' => 'admin_agile_seller_ratings',
                'parentClassName' => 'MultipleSellersParent',
                'isActive' => true,
            ],
            [
                'className' => 'SellerLocations',
                'tabName' => 'Seller Shipping Locations',
                'routeName' => 'admin_agile_seller_locations',
                'parentClassName' => 'MultipleSellersParent',
                'isActive' => true,
            ],
        ];

        $comissionTabs = [
            [
                'className' => 'SellerCommissionsParent',
                'tabName' => 'Seller Commissions',
                'routeName' => false,
                'parentClassName' => 'AdminAgileModulesParent',
                'isActive' => true,
            ],
            [
                'className' => 'AdminCommissionBase',
                'tabName' => 'Transaction Fees',
                'routeName' => 'admin_agile_commissions_base',
                'parentClassName' => 'SellerCommissionsParent',
                'isActive' => true,
            ],
            [
                'className' => 'AdminCommissionRate',
                'tabName' => 'Commission Rates',
                'routeName' => 'admin_agile_commissions_rate',
                'parentClassName' => 'SellerCommissionsParent',
                'isActive' => true,
            ],
            [
                'className' => 'AdminCommissions',
                'tabName' => 'Account History',
                'routeName' => 'admin_agile_commissions',
                'parentClassName' => 'SellerCommissionsParent',
                'isActive' => true,
            ],
            [
                'className' => 'AdminCommissionBalances',
                'tabName' => 'Account Balance',
                'routeName' => 'admin_agile_commissions_balances',
                'parentClassName' => 'SellerCommissionsParent',
                'isActive' => true,
            ],
        ];

        $membershipsTabs = [
            [
                'className' => 'SellerMembershipsParent',
                'tabName' => 'Affiliate/Memberships',
                'routeName' => false,
                'parentClassName' => 'AdminAgileModulesParent',
                'isActive' => true,
            ],
            [
                'className' => 'AdminSellerMemberships',
                'tabName' => 'Seller Memberships',
                'routeName' => 'admin_agile_seller_memberships',
                'parentClassName' => 'SellerMembershipsParent',
                'isActive' => true,
            ],
            [
                'className' => 'AdminSellerMembershipsTypes',
                'tabName' => 'Membership Types',
                'routeName' => 'admin_agile_seller_memberships_types',
                'parentClassName' => 'SellerMembershipsParent',
                'isActive' => true,
            ],
        ];

        $configTabs = [
            [
                'className' => 'AdminSellerConfiguration',
                'tabName' => 'Configuration',
                'routeName' => 'admin_agile_configuration',
                'parentClassName' => 'AdminAgileModulesParent',
                'isActive' => true,
                'icon' => ' ', // [space] - to hide icon in the menu sidebar
            ],
        ];

        $tabs = array_merge($tabs, $multipleSellerTabs, $comissionTabs, $membershipsTabs, $configTabs);

        foreach ($tabs as $tab) {
            $icon = null;
            if (isset($tab['icon'])) {
                $icon = $tab['icon'];
            }
            if (!$this->createTab(
                $tab['className'],
                $tab['tabName'],
                $tab['routeName'],
                $tab['parentClassName'],
                $tab['isActive'],
                $icon
            )) {
                return false;
            }
        }

        return true;
    }

    private function createTab($className, $tabName, $routeName, $parentClassName, $isActive, $icon = null)
    {
        if ($tabId = (int) \Tab::getIdFromClassName($className)) {
            return true;
        }

        if (!$tabId) {
            $tabId = null;
        }

        $tab = new \Tab($tabId);
        $tab->active = $isActive;
        $tab->class_name = $className;
        $tab->icon = $icon;
        $tab->name = [];

        foreach (\Language::getLanguages(true) as $lang) {
            $tab->name[$lang['id_lang']] = $this->translator->trans($tabName, [], 'Modules.Agilemultisellerpro.Admin');
        }

        $tab->wording = $tabName;
        $tab->wording_domain = 'Modules.Agilemultisellerpro.Admin';
        $tab->id_parent = 0;

        if (false !== $parentClassName) {
            $tab->id_parent = (int) \Tab::getIdFromClassName($parentClassName);
        }

        if (false !== $routeName) {
            $tab->route_name = $routeName;
        }

        $tab->module = $this->module->name;

        return $tab->save();
    }

    private function setDefaultConfiguration()
    {
        // Commissions
        $this->agileSetDefaultConfig('AGILE_MS_LOCATION_BLOCK_LEVEL', 'country');
        $this->agileSetDefaultConfig(CommissionsDataConfiguration::ASC_COMMISSION_MODE, 0);
        $this->agileSetDefaultConfig(CommissionsDataConfiguration::ASC_SHIPPING_INCLUDE, 1);
        $this->agileSetDefaultConfig(CommissionsDataConfiguration::ASC_TAX_INCLUDE, 1);
        $this->agileSetDefaultConfig(CommissionsDataConfiguration::ASC_VOUCHER_COST, 1);
        $this->agileSetDefaultConfig(CommissionsDataConfiguration::ASC_RT_COMMISSION_AT, json_encode([6, 7]));
        $this->agileSetDefaultConfig(CommissionsDataConfiguration::ASC_CT_COMMISSION_AT, json_encode([2, 11]));

        // Membership
        $this->agileSetDefaultConfig(MembershipDataConfiguration::AGILE_MEMBERSHIP_STATUS, 0);
        $this->agileSetDefaultConfig(MembershipDataConfiguration::AGILE_MEMBERSHIP_CID, 0);
        $this->agileSetDefaultConfig(MembershipDataConfiguration::AGILE_MEMBERSHIP_PAUSE_GRACEDAYS, 0);
        $this->agileSetDefaultConfig(MembershipDataConfiguration::AGILE_MEMBERSHIP_FREE_ONETIME_ONLY, 1);
        $this->agileSetDefaultConfig(MembershipDataConfiguration::AGILE_MEMBERSHIP_FREE_TRIAL_ID, $this->trialMembershipTypeId);
        $this->agileSetDefaultConfig(MembershipDataConfiguration::AGILE_MEMBERSHIP_FREE_TRIAL_TIMING, MembershipDataConfiguration::TIMING_NEW_SELLER);
        $this->agileSetDefaultConfig(MembershipDataConfiguration::AGILE_MEMBERSHIP_FREE_TRIAL_STATE, 0);
        $this->agileSetDefaultConfig(MembershipDataConfiguration::AGILE_MEMBERSHIP_REMINDER_DAYS, 10);

        \Configuration::updateValue(
            CommissionsDataConfiguration::ASC_COMMISSION_CURRENCY,
            \Configuration::get('PS_CURRENCY_DEFAULT')
        );

        return true;
    }

    public function agileSetDefaultConfig($key, $value)
    {
        if (false === \Configuration::get($key)) {
            \Configuration::updateValue($key, $value);
        }
    }

    private function prepareDefaultCommissionBase()
    {
        $sellerinfoCommissionBaseRepository = $this->entityManager->getRepository(SellerinfoCommissionBase::class);

        if (!$sellerinfoCommissionBaseRepository->count([])) {
            $sellerinfoCommissionBase = new SellerinfoCommissionBase();

            $sellerinfoCommissionBase
                ->setBaseCommission(0);

            $this->entityManager->persist($sellerinfoCommissionBase);
            $this->entityManager->flush();
        }

        return true;
    }

    private function prepareDefaultCommissionRate()
    {
        $sellerinfoCommissionRateRepository = $this->entityManager->getRepository(SellerinfoCommissionRate::class);

        if (!$sellerinfoCommissionRateRepository->count([])) {
            $sellerinfoCommissionRate = new SellerinfoCommissionRate();

            $sellerinfoCommissionRate
                ->setFromAmount(0)
                ->setToAmount(0)
                ->setCommission(10)
                ->setDeductionRate(0);

            $this->entityManager->persist($sellerinfoCommissionRate);
            $this->entityManager->flush();
        }

        return true;
    }

    private function initCriterions()
    {
        $sellerinfoRatingCriterionRepository = $this->entityManager->getRepository(SellerinfoRatingCriterion::class);

        if (!$sellerinfoRatingCriterionRepository->count([])) {
            $criterions = ['Shipping', 'Service', 'Communication'];

            $langRepository = $this->entityManager->getRepository(Lang::class);

            foreach ($criterions as $criterion) {
                $sellerinfoRatingCriterion = new SellerinfoRatingCriterion();

                foreach ($langRepository->findAll() as $lang) {
                    $sellerinfoRatingCriterionLang = new SellerinfoRatingCriterionLang();

                    $sellerinfoRatingCriterionLang
                        ->setLang($lang)
                        ->setName($criterion);

                    $sellerinfoRatingCriterion->addSellerinfoRatingCriterionLang($sellerinfoRatingCriterionLang);
                }

                $this->entityManager->persist($sellerinfoRatingCriterion);
                $this->entityManager->flush();
            }
        }

        return true;
    }

    private function setMembershipCategory()
    {
        $id_cate = (int) \Configuration::get('AGILE_MEMBERSHIP_CID');
        $category = new \Category($id_cate);
        $idGroup = (int) \Configuration::get('PS_CUSTOMER_GROUP');

        if (\Validate::isLoadedObject($category)) {
            return true;
        }

        $category = AgileHelper::createCategoryByName('Memberships');

        \Configuration::updateValue('AGILE_MEMBERSHIP_CID', $category->id);

        $imageurl = \Tools::getShopDomain(true, true) . __PS_BASE_URI__
            . 'modules/agilemultisellerpro/views/img/membership/memberships.jpg';

        if (!AgileHelper::addCategoryImage($category->id, $imageurl)) {
            $this->_errors[] = $this->translator->trans('Failed to add a image for Memberships category.', [], 'Modules.Agilemultisellerpro.Admin');
        }

        $basicproduct = $this->prepareMembershipProduct($category->id, 'Basic membership', 50, true, true);

        $sellerinfoMembershipTypeRepository = $this->entityManager->getRepository(SellerinfoMembershipType::class);

        $basictype = $sellerinfoMembershipTypeRepository->findOneBy([
            'idProduct' => $basicproduct->id,
        ]);

        if (!$basictype) {
            $this->prepareDefaultMembershipType($basicproduct->id, 'MONTH', 1, $idGroup, 100, 5);
        }

        $advancedproduct = $this->prepareMembershipProduct($category->id, 'Advanced membership', 100, true, true);

        $advancedtype = $sellerinfoMembershipTypeRepository->findOneBy([
            'idProduct' => $advancedproduct->id,
        ]);

        if (!$advancedtype) {
            $this->prepareDefaultMembershipType($advancedproduct->id, 'MONTH', 6, $idGroup, null, 20);
        }

        $trialProduct = $this->prepareMembershipProduct($category->id, 'Trial plan', 0, true, false);

        $trialType = $sellerinfoMembershipTypeRepository->findOneBy([
            'idProduct' => $trialProduct->id,
        ]);

        if (!$trialType) {
            $trialType = $this->prepareDefaultMembershipType($trialProduct->id, 'DAY', 14, $idGroup, 10, 3);
        }

        $this->trialMembershipTypeId = (int) $trialType->getIdMembershipType();

        return true;
    }

    private function prepareMembershipProduct($id_category, $name, $price, $is_virtual = true, $active = true)
    {
        $product = AgileHelper::createProductWithBasics($id_category, $name, $price, $is_virtual, $active);

        if (file_exists(_PS_ROOT_DIR_ . '/modules/agilemultisellerpro/views/img/membership/' . strtolower(str_replace(' ', '', $name)) . '.jpg')) {
            $imageurl = \Tools::getShopDomain(true, true) . __PS_BASE_URI__ . 'modules/agilemultisellerpro/views/img/membership/' . strtolower(str_replace(' ', '', $name)) . '.jpg';

            AgileHelper::addProductImage($product->id, $imageurl);
        }

        return $product;
    }

    private function prepareDefaultMembershipType($id_product, $interval, $units, $id_group = 1, $tisting_max = null, $product_images_max = null)
    {
        $membertype = new SellerinfoMembershipType();
        $membertype->setIdProduct($id_product);
        $membertype->setIntervalMembership($interval);
        $membertype->setUnits($units);
        $membertype->setIdGroup($id_group);
        $membertype->setListingMax($tisting_max);
        $membertype->setProductImages($product_images_max);

        $this->entityManager->persist($membertype);
        $this->entityManager->flush();

        return $membertype;
    }
}
