<?php
/**
 * NOTICE OF LICENSE.
 *
 * Copyright 2022 Kosmonaft.dev
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 *  @author    Alexandre DEBUSSCHÈRE <alexandre@kosmonaft.dev>
 *  @copyright 2022 - 2023 Kosmonaft.dev
 *  @license   MIT
 */

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

/**
 * Class MRMaxTrackingModuleFrontController
 */
class MRMaxTrackingModuleFrontController extends ModuleFrontController
{

    /** @var bool */
    public $auth = false;

    /** @var bool */
    public $ajax;

    /** @var bool */
    protected $debug;

    /**
     * @return void
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function display()
    {
        $this->ajax = 1;
        if (Tools::getValue('token') !== Configuration::get('MRMAX_TOKEN')) {
            header('HTTP/1.1 401 Unauthorized', true, 401);
            exit;
        }

        $trading = Configuration::get('MRMAX_TRADING_NAME');
        $brand = Configuration::get('MRMAX_BRAND_CODE');
        $code = Configuration::get('MRMAX_WS_KEY');
        if (!Tools::strlen($trading) || !Tools::strlen($code)) {
            header('HTTP/1.1 400 Bad Request', true, 400);
            exit;
        }

        $id_employee = (int)Configuration::get('MRMAX_EMPLOYEE_ID');
        $id_order_registered = (int)Configuration::get('MRMAX_REGISTERED_PACKAGE_STATE');
        $id_order_shipped = (int)Configuration::get('MRMAX_INCHARGE_PACKAGE_STATE');
        $id_order_delivered = (int)Configuration::get('MRMAX_DELIVERED_PACKAGE_STATE');
        $id_order_anomaly = (int)Configuration::get('MRMAX_ANOMALY_PACKAGE_STATE');

        $deliveries = MRMaxDelivery::getPaginatedOrders(0, 200, true);

        $tracking_numbers = array_combine(
            array_column($deliveries, 'id_order'),
            array_column($deliveries, 'shipping_number')
        );

        $api = new MRMaxAPI($trading, $brand, $code);

        foreach ($api->getTrackings($tracking_numbers) as $id_order => $timeline) {
            $order = new Order((int)$id_order);
            if (!Validate::isLoadedObject($order)) {
                printf('Order #%s cannot be loaded...<br>', $id_order);
                continue;
            }

            $code = !empty($timeline->WSI2_TracingColisDetailleResult->STAT) ?
                $timeline->WSI2_TracingColisDetailleResult->STAT :
                null;

            $tracking = MRMaxTracking::getByIdOrder($id_order);
            if (Validate::isLoadedObject($tracking) && $tracking->code == $code) {
                printf('Order #%s has same tracking,  no update needed.<br>', $id_order);
                continue;
            }

            if (!isset($timeline->WSI2_TracingColisDetailleResult->Tracing->ret_WSI2_sub_TracingColisDetaille)) {
                printf(
                    'Order #%s, unable to retrieve tracking information (STAT #%s).<br>',
                    $id_order,
                    $timeline->WSI2_TracingColisDetailleResult->STAT
                );
                continue;
            }

            $details = $timeline->WSI2_TracingColisDetailleResult->Tracing->ret_WSI2_sub_TracingColisDetaille;
            $step = array_reduce($details, function ($latest, $detail) {
                if (Tools::strlen($detail->Libelle)) {
                    $latest = $detail;
                }

                return $latest;
            }, []);

            $tracking = new MRMaxTracking();
            $tracking->id_order = $id_order;
            $tracking->id_step = 1;
            $tracking->label_short = $step->Libelle;
            $tracking->label_long = $step->Libelle;
            $tracking->code = $code;
            $tracking->date = DateTimeImmutable::createFromFormat(
                'd/m/y H:i',
                sprintf('%s %s', $step->Date, $step->Heure)
            )->format('Y-m-d H:i:s');
            $tracking->add();

            if ($id_order_delivered && $tracking->code == 82 && $order->current_state != $id_order_delivered) {
                // Package delivered
                $order->setCurrentState($id_order_delivered, $id_employee) ?
                    printf('Order #%s changed status to "DELIVERED".<br>', $id_order) :
                    printf('Order #%s did not change status to "DELIVERED", an error occured...<br>', $id_order);
            } elseif ($id_order_shipped && $tracking->code == 81 && $order->current_state != $id_order_shipped) {
                // Package shipped
                $order->setCurrentState($id_order_shipped, $id_employee) ?
                    printf('Order #%s changed status to "SHIPPED".<br>', $id_order) :
                    printf('Order #%s did not change status to "SHIPPED", an error occured...<br>', $id_order);
            } elseif ($id_order_registered && $tracking->code == 80 && $order->current_state != $id_order_registered) {
                // Package registered
                $order->setCurrentState($id_order_registered, $id_employee) ?
                    printf('Order #%s changed status to "REGISTERED".<br>', $id_order) :
                    printf('Order #%s did not change status to "REGISTERED", an error occured...<br>', $id_order);
            } elseif ($id_order_anomaly && $tracking->code == 83 && $order->current_state != $id_order_anomaly) {
                // Package anomaly
                $order->setCurrentState($id_order_anomaly, $id_employee) ?
                    printf('Order #%s changed status to "ANOMALY".<br>', $id_order) :
                    printf('Order #%s did not change status to "ANOMALY", an error occured...<br>', $id_order);
            } else {
                printf('Order #%s, tracking created, waiting for tracking update.<br>', $id_order);
            }
        }

        header('Content-Type: text/html', true, 200);
        $this->ajaxDie();
    }
}
