<?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
 */

use PrestaShop\Module\AgileMultisellerPro\Controller\Front\AgileModuleFrontController;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoCartCarrier;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoLocationCarrier;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoOrder;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoOrderDetail;

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

class AgileMultiSellerProSellerOrderDetailModuleFrontController extends AgileModuleFrontController
{
    private $order;

    public function init()
    {
        parent::init();

        $reference = Tools::getValue('ref_order');
        $reference = $reference && Validate::isReference($reference) ? $reference : false;
        $this->order = $reference ? Order::getByReference($reference)->getFirst() : false;
    }

    public function setMedia()
    {
        parent::setMedia();

        $this->registerStylesheet(
            'agile_orders',
            '/modules/agilemultisellerpro/views/css/front/orders.css',
            ['media' => 'all', 'priority' => 100]
        );
    }

    public function initContent()
    {
        parent::initContent();

        $order = null;

        if (true === $this->isSellerInfoProduct()) {
            $order = $this->order;
            $idCart = $order->id_cart;

            $idSellerinfo = $this->sellerinfo->getIdSellerinfo();

            $sellerInfoCartCarrierRepository = $this->entityManager->getRepository(SellerinfoCartCarrier::class);

            $sellerCartCarrier = $sellerInfoCartCarrierRepository->findOneBy([
                'idCart' => $idCart,
                'idSellerInfo' => $idSellerinfo,
            ]);

            if ($sellerCartCarrier) {
                $carrier = Carrier::getCarrierByReference(
                    $sellerCartCarrier->getIdCarrierReference(),
                    (int) $order->id_lang
                );
            } else {
                $carrier = new Carrier();
            }

            $id_order_state = (int) $order->getCurrentState();
            $addressInvoice = new Address((int) $order->id_address_invoice);
            $addressDelivery = new Address((int) $order->id_address_delivery);

            $inv_adr_fields = AddressFormat::getOrderedAddressFields($addressInvoice->id_country);
            $dlv_adr_fields = AddressFormat::getOrderedAddressFields($addressDelivery->id_country);

            $invoiceAddressFormatedValues = AddressFormat::getFormattedAddressFieldsValues(
                $addressInvoice,
                $inv_adr_fields
            );
            $deliveryAddressFormatedValues = AddressFormat::getFormattedAddressFieldsValues(
                $addressDelivery,
                $dlv_adr_fields
            );

            if ($order->total_discounts > 0) {
                $this->context->smarty->assign('total_old', (float) ($order->total_paid - $order->total_discounts));
            }

            $products = $order->getProducts();

            $use_tax = (int) Configuration::get('PS_TAX') == 1;

            $sellerOrderDetailRepository = $this->entityManager->getRepository(SellerinfoOrderDetail::class);
            foreach ($products as $k => $product) {
                // check that the product assigned to seller
                $sellerProduct = $sellerOrderDetailRepository->findOneBy([
                    'sellerInfo' => $this->sellerinfo,
                    'idOrderDetail' => (int) $product['id_order_detail'],
                    'idProduct' => (int) $product['product_id'],
                ]);

                if (!$sellerProduct) {
                    // delete product from list if not assigned to seller
                    unset($products[$k]);
                }
            }

            // recalculate order total
            $order->total_products_wt = 0;
            foreach ($products as $product) {
                $order->total_products_wt += ($use_tax ? $product['total_price_tax_incl'] : $product['total_price_tax_excl']);
            }
            $order->total_paid = $order->total_products_wt;

            $customizedDatas = Product::getAllCustomizedDatas((int) $order->id_cart);
            Product::addCustomizationPrice($products, $customizedDatas);

            $customer = new Customer($order->id_customer);

            $order_states = OrderState::getOrderStates((int) $this->context->language->id);

            $this->context->smarty->assign([
                'order_states' => $order_states,
                'shop_name' => (string) Configuration::get('PS_SHOP_NAME'),
                'return_allowed' => (int) $order->isReturnable(),
                'currency' => new Currency($order->id_currency),
                'order_cur_state' => (int) $id_order_state,
                'invoiceAllowed' => (int) Configuration::get('PS_INVOICE'),
                'invoice' => (OrderState::invoiceAvailable($id_order_state) && $order->invoice_number),
                'order_history' => $order->getHistory($this->context->language->id, false, true),
                'products' => $products,
                'discounts' => $order->getCartRules(),
                'carrier' => $carrier,
                'address_invoice' => $addressInvoice,
                'invoiceState' => (Validate::isLoadedObject($addressInvoice) && $addressInvoice->id_state) ?
                    new State($addressInvoice->id_state) : false,
                'address_delivery' => $addressDelivery,
                'inv_adr_fields' => $inv_adr_fields,
                'dlv_adr_fields' => $dlv_adr_fields,
                'invoiceAddressFormatedValues' => $invoiceAddressFormatedValues,
                'deliveryAddressFormatedValues' => $deliveryAddressFormatedValues,
                'deliveryState' => (Validate::isLoadedObject($addressDelivery) && $addressDelivery->id_state) ?
                    new State($addressDelivery->id_state) : false,
                'is_guest' => false,
                'messages' => CustomerMessage::getMessagesByOrderId((int) $order->id, false),
                'CUSTOMIZE_FILE' => Product::CUSTOMIZE_FILE,
                'CUSTOMIZE_TEXTFIELD' => Product::CUSTOMIZE_TEXTFIELD,
                'isRecyclable' => Configuration::get('PS_RECYCLABLE_PACK'),
                'use_tax' => $use_tax,
                'group_use_tax' => (Group::getPriceDisplayMethod($customer->id_default_group) == PS_TAX_INC),
                'customizedDatas' => $customizedDatas,
            ]);

            if ($carrier->url && $sellerCartCarrier->getTrackingNumber()) {
                $this->context->smarty->assign(
                    'followup',
                    str_replace('@', $sellerCartCarrier->getTrackingNumber(), $carrier->url)
                );
            }

            $this->context->smarty->assign(
                'HOOK_ORDERDETAILDISPLAYED',
                Hook::exec('displayOrderDetail', ['order' => $order])
            );

            Hook::exec('actionOrderDetail', ['carrier' => $carrier, 'order' => $order]);

            unset($carrier, $addressInvoice, $addressDelivery);
        } else {
            $this->errors[] = $this->l('You do not have permission to view this order.');
        }

        $sellerinfoCartCarrierRepository = $this->entityManager->getRepository(SellerinfoCartCarrier::class);

        $sellerinfoCartCarrier = $sellerinfoCartCarrierRepository->findOneBy([
            'idSellerInfo' => $this->sellerinfo->getIdSellerinfo(),
            'idCart' => $this->order->id_cart,
        ]);

        $shipping = null;

        $order->total_shipping = 0;
        if ($sellerinfoCartCarrier) {
            $sellerCarrier = Carrier::getCarrierByReference($sellerinfoCartCarrier->getIdCarrierReference());

            $defaultCurrency = Currency::getDefaultCurrency();

            $sellerinfoLocationCarrierRepository = $this->entityManager->getRepository(SellerinfoLocationCarrier::class);
            $location = '';

            if ($sellerinfoCartCarrier->getIdLocationCarrier()) {
                $sellerinfoLocationCarrier = $sellerinfoLocationCarrierRepository->find($sellerinfoCartCarrier->getIdLocationCarrier());

                if ($sellerinfoLocationCarrier) {
                    $location = $sellerinfoLocationCarrier->getLocation();
                }
            }

            $shipping = [
                'carrierName' => $sellerCarrier->name,
                'weight' => $sellerinfoCartCarrier->getWeight(),
                'shippingCost' => Tools::convertPriceFull(
                    $sellerinfoCartCarrier->getShippingCost(),
                    $defaultCurrency,
                    new Currency($this->order->id_currency)
                ),
                'trackingNumber' => $sellerinfoCartCarrier->getTrackingNumber(),
                'idCarrierReference' => $sellerinfoCartCarrier->getIdCarrierReference(),
                'idSellerInfo' => $this->sellerinfo->getIdSellerinfo(),
                'idCart' => $this->order->id_cart,
                'location' => $location,
            ];

            // recalculate total shipping and total order
            $order->total_shipping = $shipping['shippingCost'];
            $order->total_paid += $order->total_shipping;
        }

        $this->context->smarty->assign([
            'seller_tab_id' => 4,
            'order' => $order,
            'shipping' => $shipping,
        ]);

        $this->setTemplate('module:agilemultisellerpro/views/templates/front/orders/sellerorderdetail.tpl');
    }

    public function postProcess()
    {
        $order = $this->order;

        if (!Validate::isLoadedObject($order)) {
            $this->errors[] = $this->l('Order not found or you do not have permission to view this order.');

            return;
        }

        if (false === $this->isSellerInfoProduct()) {
            return;
        }

        if (Tools::isSubmit('submitShippingNumber')
            && Tools::getIsset('idCarrierReference')
            && Tools::getIsset('idSellerInfo')
            && Tools::getIsset('idCart')
            && Tools::getIsset('tracking_number')
        ) {
            $idCarrierReference = Tools::getValue('idCarrierReference');
            $idSellerInfo = Tools::getValue('idSellerInfo');
            $idCart = Tools::getValue('idCart');
            $trackingNumber = trim(Tools::getValue('tracking_number'));

            $sellerinfoCartCarrierRepository = $this->entityManager->getRepository(SellerinfoCartCarrier::class);

            $sellerinfoCartCarrier = $sellerinfoCartCarrierRepository->findOneBy([
                'idSellerInfo' => $idSellerInfo,
                'idCart' => $idCart,
            ]);

            if ($trackingNumber && !Validate::isTrackingNumber($trackingNumber)) {
                $this->errors[] = $this->l('The tracking number is incorrect.');
            } else {
                $sellerinfoCartCarrier->setTrackingNumber($trackingNumber);

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

                $customer = new Customer((int) $order->id_customer);

                $carrier = Carrier::getCarrierByReference($idCarrierReference, $order->id_lang);

                if (!Validate::isLoadedObject($customer)) {
                    throw new PrestaShopException('Can\'t load Customer object');
                }

                if (!Validate::isLoadedObject($carrier)) {
                    throw new PrestaShopException('Can\'t load Carrier object');
                }

                $templateVars = [
                    '{followup}' => str_replace('@', $trackingNumber, $carrier->url),
                    '{firstname}' => $customer->firstname,
                    '{lastname}' => $customer->lastname,
                    '{id_order}' => $order->id,
                    '{shipping_number}' => $trackingNumber,
                    '{order_name}' => $order->getUniqReference(),
                ];

                if (@Mail::Send(
                    (int) $order->id_lang,
                    'in_transit',
                    Mail::l('Package in transit', (int) $order->id_lang),
                    $templateVars,
                    $customer->email,
                    $customer->firstname . ' ' . $customer->lastname,
                    null,
                    null,
                    null,
                    null,
                    _PS_MAIL_DIR_,
                    true,
                    (int) $order->id_shop
                )) {
                    Hook::exec(
                        'actionAdminOrdersTrackingNumberUpdate',
                        [
                            'order' => $order,
                            'customer' => $customer,
                            'carrier' => $carrier,
                        ],
                        null,
                        false,
                        true,
                        false,
                        $order->id_shop
                    );
                } else {
                    $this->errors[] = $this->l(
                        'An error occurred while sending an email to the customer.'
                    );
                }
            }
        } elseif (Tools::isSubmit('submitState') && Tools::getIsset('id_order')) {
            $order_state = new OrderState(Tools::getValue('id_order_state'));

            if (!Validate::isLoadedObject($order_state)) {
                $this->errors[] = $this->l('Invalid new order status');
            } else {
                $current_order_state = $order->getCurrentOrderState();

                if ($current_order_state->id != $order_state->id) {
                    $history = new OrderHistory();
                    $history->id_order = $order->id;

                    $history->changeIdOrderState($order_state->id, $order->id);

                    $carrier = new Carrier($order->id_carrier, $order->id_lang);
                    $templateVars = [];

                    if ($history->id_order_state == Configuration::get('PS_OS_SHIPPING') && $order->shipping_number) {
                        $templateVars = [
                            '{followup}' => str_replace('@', $order->shipping_number, $carrier->url),
                        ];
                    } elseif ($history->id_order_state == Configuration::get('PS_OS_CHEQUE')) {
                        $templateVars = [
                            '{cheque_name}' => (Configuration::get('CHEQUE_NAME') ?
                                Configuration::get('CHEQUE_NAME') : ''),
                            '{cheque_address_html}' => (Configuration::get('CHEQUE_ADDRESS') ?
                                nl2br(Configuration::get('CHEQUE_ADDRESS')) : ''),
                        ];
                    } elseif ($history->id_order_state == Configuration::get('PS_OS_BANKWIRE')) {
                        $templateVars = [
                            '{bankwire_owner}' => (Configuration::get('BANK_WIRE_OWNER') ?
                                Configuration::get('BANK_WIRE_OWNER') : ''),
                            '{bankwire_details}' => (Configuration::get('BANK_WIRE_DETAILS') ?
                                nl2br(Configuration::get('BANK_WIRE_DETAILS')) : ''),
                            '{bankwire_address}' => (Configuration::get('BANK_WIRE_ADDRESS') ?
                                nl2br(Configuration::get('BANK_WIRE_ADDRESS')) : ''),
                        ];
                    }

                    if (!$history->addWithemail(true, $templateVars)) {
                        $this->errors[] = $this->l(
                            'An error occurred while changing the status or was unable to send e-mail to the customer.'
                        );
                    }
                } else {
                    $this->errors[] = $this->l('This order is already assigned this status');
                }
            }

            if (empty($this->errors)) {
                $this->context->smarty->assign('cfmmsg_flag', 1);
            }
        }

        if (Tools::isSubmit('submitMessage')) {
            $idOrder = (int) Tools::getValue('id_order');
            $msgText = Tools::getValue('msgText');

            if (!$idOrder || !Validate::isUnsignedId($idOrder)) {
                $this->errors[] = $this->l('Order is no longer valid');
            } elseif (empty($msgText)) {
                $this->errors[] = $this->l('Message cannot be blank');
            } elseif (!Validate::isMessage($msgText)) {
                $this->errors[] = $this->l('Message is invalid (HTML is not allowed)');
            }

            if (!count($this->errors)) {
                $order = new Order($idOrder);

                if (Validate::isLoadedObject($order)) {
                    // $seller = new Employee((int)SellerInfo::getSellerIdByCustomerId($this->context->customer->id));
                    $customer = new Customer($order->id_customer);
                    $customerSeller = new Customer($this->sellerinfo->getIdCustomer());

                    $id_customer_thread = CustomerThread::getIdCustomerThreadByEmailAndIdOrder(
                        $customerSeller->email,
                        $order->id
                    );

                    $cm = new CustomerMessage();

                    if (!$id_customer_thread) {
                        $ct = new CustomerThread();
                        $ct->id_contact = 2;
                        $ct->id_customer = (int) $customerSeller->id;
                        $ct->id_shop = (int) $this->context->shop->id;
                        $id_product = (int) Tools::getValue('id_product');
                        if ($id_product && $order->orderContainProduct($id_product)) {
                            $ct->id_product = $id_product;
                        }
                        $ct->id_order = (int) $order->id;
                        $ct->id_lang = (int) $this->context->language->id;
                        $ct->email = $customerSeller->email;
                        $ct->status = 'open';
                        $ct->token = Tools::passwdGen(12);
                        $ct->add();
                    } else {
                        $ct = new CustomerThread((int) $id_customer_thread);
                    }

                    $cm->id_customer_thread = $ct->id;
                    $cm->message = $msgText;
                    $cm->ip_address = ip2long($_SERVER['REMOTE_ADDR']);
                    $cm->add();

                    $to = $customer->email;
                    $toName = $customer->firstname . ' ' . $customer->lastname;

                    $from = $customerSeller->email;
                    $fromName = $this->sellerinfo
                        ->getLangByLangId((int) $this->context->language->id)
                        ->getCompany();

                    if (Validate::isLoadedObject($customer)) {
                        Mail::Send(
                            $this->context->language->id,
                            'order_merchant_comment',
                            Mail::l('Message from a seller'),
                            [
                                '{lastname}' => $customer->lastname,
                                '{firstname}' => $customer->firstname,
                                '{email}' => $customer->email,
                                '{id_order}' => (int) $order->id,
                                '{order_name}' => $order->getUniqReference(),
                                '{message}' => Tools::nl2br($msgText),
                            ],
                            $to,
                            $toName,
                            $from,
                            $fromName
                        );

                        Tools::redirect($this->context->link->getModuleLink(
                            'agilemultisellerpro', 'sellerorderdetail', ['ref_order' => $order->reference], true
                        ));
                    }
                } else {
                    $this->errors[] = $this->l('Order not found');
                }
            }
        }
    }

    private function isSellerInfoProduct()
    {
        if (
            !Validate::isLoadedObject($this->order)
            || !$this->entityManager->getRepository(SellerinfoOrder::class)
                ->findOneBy(['sellerInfo' => $this->sellerinfo, 'idOrder' => $this->order->id])
        ) {
            return false;
        }

        return true;
    }
}
