<?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\SellerinfoOrder;
use PrestaShop\Module\AgileMultisellerPro\Helper\AgileHelper;
use PrestaShop\PrestaShop\Core\Product\Search\Pagination;

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

class AgileMultiSellerProSellerOrdersModuleFrontController extends AgileModuleFrontController
{
    private $sellerInfoOrderRepository;

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

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

        $this->registerJavascript(
            'agile_sellerorders',
            '/modules/agilemultisellerpro/views/js/front/sellerorders.js',
            ['position' => 'bottom', 'priority' => 100]
        );

        $this->registerJavascript(
            'agile_sellerpage',
            '/modules/agilemultisellerpro/views/js/front/sellerpage.js',
            ['position' => 'bottom', 'priority' => 100]
        );
    }

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

        $this->n = (int) Tools::getValue('n');
        $this->p = (int) Tools::getValue('page');

        if ($this->p <= 0) {
            $this->p = 1;
        }

        if ($this->n <= 0) {
            $this->n = max(1, (int) Configuration::get('PS_PRODUCTS_PER_PAGE'));
        }

        $this->orderBy = Tools::getValue('orderBy');

        if (empty($this->orderBy)) {
            $this->orderBy = 'o.date_add';
        }

        $this->orderWay = Tools::getValue('orderWay');

        if (empty($this->orderWay)) {
            $this->orderWay = 'DESC';
        }

        $orders = $this->getSellerInfoOrderRepository()->getOrders(
            $this->sellerinfo->getIdSellerinfo(),
            true,
            $this->context,
            false,
            $this->p,
            $this->n,
            $this->orderBy,
            $this->orderWay,
            $this->getExtraConditions()
        );

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

        $this->context->smarty->assign([
            'seller_tab_id' => 4,
            'orders' => $orders,
            'pagination' => $this->getTemplateVarPagination(),
            'n' => $this->n,
            'p' => $this->p,
            'orderBy' => $this->orderBy,
            'orderWay' => $this->orderWay,
            'statuses' => $statuses,
            'invoiceAllowed' => (int) Configuration::get('PS_INVOICE'),
            'filter_date_add_from' => Tools::getValue('filter_date_add_from'),
            'filter_date_add_to' => Tools::getValue('filter_date_add_to'),
            'filter_id_order_state' => Tools::getValue('filter_id_order_state'),
            'filter_id_order' => Tools::getValue('filter_id_order'),
            'filter_reference' => Tools::getValue('filter_reference'),
            'filter_customer' => Tools::getValue('filter_customer'),
            'filter_total' => Tools::getValue('filter_total'),
            'filter_payment' => Tools::getValue('filter_payment'),
        ]);

        Media::addJsDef([
            'listurl' => $this->context->link->getModuleLink(
                'agilemultisellerpro',
                'sellerorders',
                [],
                true
            ),
            'n' => $this->n,
            'p' => $this->p,
            'orderBy' => $this->orderBy,
            'orderWay' => $this->orderWay,
        ]);

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

    protected function getExtraConditions()
    {
        $extraCondition = '';
        $filters = [
            ['name' => 'filter_id_order', 'type' => 'number'],
            ['name' => 'filter_reference', 'type' => 'text'],
            ['name' => 'filter_customer', 'type' => 'text'],
            ['name' => 'filter_payment', 'type' => 'text'],
            ['name' => 'filter_total', 'type' => 'float'],
            ['name' => 'filter_id_order_state', 'type' => 'number'],
            ['name' => 'filter_date_add', 'type' => 'date'],
        ];

        foreach ($filters as $filter) {
            $val = Tools::getValue($filter['name']);
            $len = Tools::strlen($val);

            switch ($filter['name']) {
                case 'filter_id_order':
                    if ((int) $val > 0) {
                        $extraCondition = $extraCondition . ' AND o.id_order = ' . (int) $val;
                    }
                    break;
                case 'filter_reference':
                    if ($len > 0) {
                        $extraCondition = $extraCondition . " AND o.reference LIKE '%" . pSQL($val) . "%'";
                    }
                    break;
                case 'filter_customer':
                    if ($len > 0) {
                        $extraCondition = $extraCondition . " AND (c.firstname LIKE '%" . pSQL($val) .
                            "%' OR c.lastname LIKE '%" . pSQL($val) . "%')";
                    }
                    break;
                case 'filter_id_order_state':
                    if ($val > 0) {
                        $extraCondition = $extraCondition . ' AND o.current_state =' . (int) $val;
                    }
                    break;
                case 'filter_total':
                    if ($len > 0) {
                        $extraCondition = $extraCondition . ' AND o.total_paid =' . (float) $val;
                    }
                    break;
                case 'filter_payment':
                    if ($len > 0) {
                        $extraCondition = $extraCondition . " AND o.payment like '%" . pSQL($val) . "%'";
                    }
                    break;
                case 'filter_date_add':
                    $from = Tools::getValue($filter['name'] . '_from');
                    $to = Tools::getValue($filter['name'] . '_to');
                    if (!empty($from)) {
                        $extraCondition = $extraCondition . " AND o.date_add >='" . pSQL($from) . "'";
                    }
                    if (!empty($to)) {
                        $extraCondition = $extraCondition . " AND o.date_add <='" . pSQL($to) . "'";
                    }
                    break;
            }
        }

        return $extraCondition;
    }

    private function getTemplateVarPagination()
    {
        $totalOrdersCount = $this->getSellerInfoOrderRepository()
            ->getOrders(
                $this->sellerinfo->getIdSellerinfo(),
                true,
                $this->context,
                true,
                $this->p,
                $this->n,
                $this->orderBy,
                $this->orderWay,
                $this->getExtraConditions()
            );

        $page = $this->p;
        $perPage = $this->n;

        $pagination = new Pagination();
        $pagination
            ->setPage($page)
            ->setPagesCount(
                (int) ceil($totalOrdersCount / $perPage)
            )
        ;

        $itemsShownFrom = ($perPage * ($page - 1)) + 1;
        $itemsShownTo = $perPage * $page;

        $pages = array_map(function ($link) {
            $link['url'] = $this->updateQueryString([
                'page' => $link['page'] > 1 ? $link['page'] : null,
            ]);

            return $link;
        }, $pagination->buildLinks());

        // Filter next/previous link on first/last page
        $pages = array_filter($pages, function ($page) use ($pagination) {
            if ('previous' === $page['type'] && 1 === $pagination->getPage()) {
                return false;
            }
            if ('next' === $page['type'] && $pagination->getPagesCount() === $pagination->getPage()) {
                return false;
            }

            return true;
        });

        return [
            'total_items' => $totalOrdersCount,
            'items_shown_from' => $itemsShownFrom,
            'items_shown_to' => ($itemsShownTo <= $totalOrdersCount) ? $itemsShownTo : $totalOrdersCount,
            'current_page' => $pagination->getPage(),
            'pages_count' => $pagination->getPagesCount(),
            'pages' => $pages,
            // Compare to 3 because there are the next and previous links
            'should_be_displayed' => (count($pagination->buildLinks()) > 3),
        ];
    }

    public function postProcess()
    {
        $export = Tools::getValue('export');

        if (!empty($export)) {
            header('Content-type: text/csv');
            header('Content-Type: application/force-download; charset=UTF-8');
            header('Cache-Control: no-store, no-cache');
            header('Content-disposition: attachment; filename="orders_' . date('Y-m-d_His') . '.csv"');

            $orders = $this->getSellerInfoOrderRepository()->getOrders(
                $this->sellerinfo->getIdSellerinfo(),
                true,
                $this->context,
                false,
                1,
                999999,
                $this->orderBy,
                $this->orderWay,
                $this->getExtraConditions(),
                false
            );

            $data = $this->processExport($orders);

            AgileHelper::hookGenerateCSV($data);
        }
    }

    public function processExport($list, $text_delimiter = '')
    {
        if (ob_get_level() && ob_get_length() > 0) {
            ob_clean();
        }

        $fields = [
            'id_order' => $this->trans('ID', [], 'Modules.Agilemultisellerpro.Orders'),
            'date_add' => $this->trans('Date', [], 'Modules.Agilemultisellerpro.Orders'),
            'reference' => $this->trans('Order Refeerence', [], 'Modules.Agilemultisellerpro.Orders'),
            'currency' => $this->trans('Currency', [], 'Modules.Agilemultisellerpro.Orders'),
            'total_paid' => $this->trans('Paid', [], 'Modules.Agilemultisellerpro.Orders'),
            'payment' => $this->trans('Payment', [], 'Modules.Agilemultisellerpro.Orders'),
            'osname' => $this->trans('Status', [], 'Modules.Agilemultisellerpro.Orders'),
            'invoice' => $this->trans('Invoice', [], 'Modules.Agilemultisellerpro.Orders'),
        ];

        $headers = [];

        foreach ($fields as $field => $header) {
            $headers[] = $header;
        }

        $content = [];

        foreach ($list as $i => $row) {
            $content[$i] = [];
            $currency = new Currency((int) $row['id_currency']);

            foreach ($fields as $field => $header) {
                switch ($field) {
                    case 'invoice':
                        $content[$i][] = $this->context->link->getModuleLink(
                            'agilemultisellerpro',
                            'sellerpdfinvoice',
                            ['id_order' => $row['id_order']]
                        );
                        break;
                    case 'currency':
                        $content[$i][] = $currency->name;
                        break;
                    default:
                        $content[$i][] = $row[$field];
                        break;
                }
            }
        }

        return [
            'export_precontent' => $this->trans('Date Range:', [], 'Modules.Agilemultisellerpro.Orders') . Tools::getValue('date_from') .
                ' - ' . Tools::getValue('date_to'),
            'export_headers' => $headers,
            'export_content' => $content,
            'text_delimiter' => $text_delimiter,
        ];
    }

    private function getSellerInfoOrderRepository()
    {
        if (empty($this->sellerInfoOrderRepository)) {
            $this->sellerInfoOrderRepository = $this->entityManager->getRepository(SellerinfoOrder::class);
        }

        return $this->sellerInfoOrderRepository;
    }
}
