<?php

declare(strict_types=1);

require_once __DIR__ . '/../../../../config/config.inc.php';

$headers = getallheaders();

header('Access-Control-Allow-Origin: ' . ($headers['origin'] ?? '*'));
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Headers: Content-Type, Authorization, Origin, Accept');
header('Access-Control-Allow-Credentials: true');

if ('OPTIONS' == $_SERVER['REQUEST_METHOD']) {
    exit(0);
}

preg_match('#^Bearer (.+)$#', $headers['authorization'] ?? $headers['Authorization'] ?? '', $matches);
if (!count($matches) || $matches[1] != \Configuration::get('MVS_REPORTING_API_ORDERS_KEY')) {
    header('HTTP/1.1 403 Forbidden');
    exit(0);
}

// Constantes
define('DATE_FORMAT', 'Y-m-d\TH:i:s');
define('ORDERS_REQUEST_RESULTS_LIMIT', 1000);

// Initialisation du container
global $kernel;
if (!$kernel) {
    require_once _PS_ROOT_DIR_ . '/app/AppKernel.php';
    $kernel = new \AppKernel('prod', false);
    $kernel->boot();
}

// Chargement du module clinique
Module::getInstanceByName('myvetshopclinique');

// Récupération et vérification sur les paramètres de date (datemin obligatoire)
$dateMin = \DateTimeImmutable::createFromFormat(DATE_FORMAT, $_REQUEST['datemin'] ?? '');
$dateMax = \DateTimeImmutable::createFromFormat(DATE_FORMAT, $_REQUEST['datemax'] ?? '') ?: new \DateTimeImmutable();
if (
    !$dateMin || $dateMin->format(DATE_FORMAT) !== $_REQUEST['datemin']
    || !$dateMax || ($_REQUEST['datemax'] && $dateMax->format(DATE_FORMAT) !== $_REQUEST['datemax'])
) {
    header('HTTP/1.1 400 Bad Request');
    exit(0);
}

// On limite le nombre de jours pour éviter la surcharge de données
$diff = $dateMin->diff($dateMax);
if ($diff->invert || $diff->format('%a') > 100) {
    header('HTTP/1.1 400 Bad Request');
    exit(0);
}

$db = \Db::getInstance();

// Préparation de la requête de récupération des commandes (avec critères de recherche)
$ordersQuery = ' FROM ' . _DB_PREFIX_ . 'orders'
    . ' WHERE ' . _DB_PREFIX_ . 'orders.invoice_date >= "' . $dateMin->format(DATE_FORMAT) . '"'
    . ' AND ' . _DB_PREFIX_ . 'orders.invoice_date <= "' . $dateMax->format(DATE_FORMAT) . '"'
    . ' ORDER BY ' . _DB_PREFIX_ . 'orders.invoice_date DESC';

// Compte des commandes trouvées selon les critères de filtres
$ordersCount = intval($db->getValue('SELECT COUNT(' . _DB_PREFIX_ . 'orders.id_order)' . $ordersQuery . ';'));

// Préparation du retour (entêtes et ouverture du tableau json)
header('Content-Type: application/json');
echo '[';

for ($i = 0; $i < $ordersCount; $i += ORDERS_REQUEST_RESULTS_LIMIT) {
    // Ajout du séparateur entre les séries de commandes
    if ($i != 0) {
        echo ',';
    }

    // Récupération des commandes
    $orders = $db->executeS('SELECT'
        . ' ' . _DB_PREFIX_ . 'orders.id_order as order_id'
        . ', ' . _DB_PREFIX_ . 'orders.invoice_date as invoice_date'
        . ', ' . _DB_PREFIX_ . 'orders.id_customer as customer_id'
        . ', ' . _DB_PREFIX_ . 'orders.current_state as state'
        . ', ' . _DB_PREFIX_ . 'orders.total_products_wt as total_products_wt'
        . ', ' . _DB_PREFIX_ . 'orders.total_paid_tax_incl as total_paid_tax_incl'
        . $ordersQuery
        . ' LIMIT ' . ORDERS_REQUEST_RESULTS_LIMIT . ' OFFSET ' . $i
        . ';'
    );

    // Constitution des listes des ids de commande pour affiner les requêtes suivantes
    $orderIds = array_unique(array_map(fn ($o) => $o['order_id'], $orders));

    $orderElements = [
        // Récupération la liste des produits pour chaque commande
        'products' => $db->executeS(
            'SELECT'
            . ' ' . _DB_PREFIX_ . 'product.id_category_default as "category"'
            . ', ' . _DB_PREFIX_ . 'order_detail.id_order as "order_id"'
            . ', ' . _DB_PREFIX_ . 'order_detail.product_name as "name"'
            . ', ' . _DB_PREFIX_ . 'order_detail.product_reference as "reference"'
            . ', ' . _DB_PREFIX_ . 'order_detail.product_quantity as "quantity"'
            . ', ' . _DB_PREFIX_ . 'order_detail.purchase_supplier_price as "purchase_price"'
            . ', ' . _DB_PREFIX_ . 'order_detail.unit_price_tax_excl as "price_tax_excl"'
            . ', ' . _DB_PREFIX_ . 'order_detail.total_price_tax_excl as "total_price_tax_excl"'
            . ', ' . _DB_PREFIX_ . 'order_detail.total_price_tax_incl as "total_price_tax_incl"'
            . ' FROM ' . _DB_PREFIX_ . 'order_detail'
            . ' LEFT JOIN ' . _DB_PREFIX_ . 'product ON ' . _DB_PREFIX_ . 'product.id_product=' . _DB_PREFIX_ . 'order_detail.product_id'
            . ' WHERE ' . _DB_PREFIX_ . 'order_detail.id_order IN (' . implode(', ', $orderIds) . ')'
            . ';'
        ),
        // Récupération des promos pour chaque commande
        'discounts' => $db->executeS(
            'SELECT'
            . ' ' . _DB_PREFIX_ . 'order_cart_rule.name as "name"'
            . ' ' . _DB_PREFIX_ . 'order_cart_rule.value as "value"'
            . ', ' . _DB_PREFIX_ . 'order_cart_rule.id_order as "order_id"'
            . ' FROM ' . _DB_PREFIX_ . 'order_cart_rule'
            . ' WHERE ' . _DB_PREFIX_ . 'order_cart_rule.id_order IN (' . implode(', ', $orderIds) . ')'
            . ';'
        ),
    ];

    // Renvoi des données
    foreach ($orders as $orderIndex => $order) {
        // Ajout du séparateur entre les commandes
        if ($orderIndex > 0) {
            echo ',';
        }

        // Nettoyage et formatage de l'objet
        $order['order_id'] = intval($order['order_id']);
        $order['customer_id'] = intval($order['customer_id']);
        $order['state'] = intval($order['state']);
        $order['total_products_wt'] = floatval($order['total_products_wt']);
        $order['total_paid_tax_incl'] = floatval($order['total_paid_tax_incl']);

        // Renvoi des infos de commande et suppression de la fermeture de l'objet pour ajouter d'autres informations
        echo rtrim(json_encode($order), '}');

        // Ajout des éléments à adjoindre
        foreach ($orderElements as $name => $elements) {
            echo ', "' . $name . '": [';
            $separator = '';
            foreach ($elements as $elementIndex => $element) {
                if ($element['order_id'] == $order['order_id']) {
                    // Nettoyage et formatage de l'objet
                    switch ($name) {
                        case 'products':
                            $element['category'] = intval($element['category']);
                            $element['quantity'] = intval($element['quantity']);
                            $element['purchase_price'] = floatval($element['purchase_price']);
                            $element['price_tax_excl'] = floatval($element['price_tax_excl']);
                            $element['total_price_tax_excl'] = floatval($element['total_price_tax_excl']);
                            $element['total_price_tax_incl'] = floatval($element['total_price_tax_incl']);
                            break;
                        case 'discounts':
                            $element['value'] = floatval($element['value']);
                            break;
                    }

                    // Suppression de l'id de commande sur l'objet produit, il est inutile pour la suite
                    unset($element['order_id']);

                    // Ajout de l'élément
                    echo $separator . json_encode($element);

                    // Suppression de l'élément pour éviter de le parcourir à nouveau pour la commande suivante
                    unset($elements[$elementIndex]);

                    // Définition du séparateur, après le premier élément, il doit être ajouté
                    $separator = ',';
                }
            }
            echo ']';
        }

        // Fermeture de l'objet de la commande
        echo '}';
    }
}

// Fermeture du tableau json
echo ']';
