<?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('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(\DateTimeInterface::ATOM, $_REQUEST['datemin'] ?? '');
$dateMax = \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $_REQUEST['datemax'] ?? '') ?: new \DateTimeImmutable();

if (
    !$dateMin || $dateMin->format(\DateTimeInterface::ATOM) !== $_REQUEST['datemin']
    || !$dateMax || ($_REQUEST['datemax'] && $dateMax->format(\DateTimeInterface::ATOM) !== $_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'
    . ' INNER JOIN ' . _DB_PREFIX_ . Clinique::TABLE . ' ON ' . _DB_PREFIX_ . 'orders.id_carrier=' . _DB_PREFIX_ . Clinique::TABLE . '.id_carrier OR ' . _DB_PREFIX_ . 'orders.id_carrier=' . _DB_PREFIX_ . Clinique::TABLE . '.id_carrier_home'
    . ' WHERE ' . _DB_PREFIX_ . 'orders.invoice_date >= "' . $dateMin->format(\DateTimeInterface::ATOM) . '"'
    . ' AND ' . _DB_PREFIX_ . 'orders.invoice_date <= "' . $dateMax->format(\DateTimeInterface::ATOM) . '"'
    . ' ORDER BY ' . _DB_PREFIX_ . 'orders.invoice_date DESC';

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

// 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 id'
        . ', ' . _DB_PREFIX_ . 'orders.invoice_date as invoice_date'
        . ', ' . _DB_PREFIX_ . Clinique::TABLE . '.id_' . Clinique::TABLE . ' as clinic_id'
        . ', ' . _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, true, false
    );

    if (!\is_array($orders)) {
        $orders = [];
    }

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

    $orderElements = [
        // Récupération la liste des produits pour chaque commande
        'products' => $db->executeS(
            'SELECT'
            . ', ' . _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_ . 'product_shop.id_category_default as "category_id"'
            . ', ' . _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_shop ON ' . _DB_PREFIX_ . 'product_shop.id_product=' . _DB_PREFIX_ . 'order_detail.product_id'
            . ' WHERE ' . _DB_PREFIX_ . 'order_detail.id_order IN (' . implode(', ', $orderIds) . ')', true, false
        ),
        // 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_tax_excl as "value_tax_excl"'
            . ', ' . _DB_PREFIX_ . 'order_cart_rule.value as "value_tax_incl"'
            . ', ' . _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) . ')', true, false
        ),
        'refunds' => $db->executeS(
            'SELECT'
            . ' ' . _DB_PREFIX_ . 'order_slip.total_products_tax_excl as "total_products_tax_excl"'
            . ', ' . _DB_PREFIX_ . 'order_slip.total_products_tax_incl as "total_products_tax_incl"'
            . ', ' . _DB_PREFIX_ . 'order_slip.total_shipping_tax_excl as "total_shipping_tax_excl"'
            . ', ' . _DB_PREFIX_ . 'order_slip.total_shipping_tax_incl as "total_shipping_tax_incl"'
            . ', ' . _DB_PREFIX_ . 'order_slip.id_order as "order_id"'
            . ' FROM ' . _DB_PREFIX_ . 'order_slip'
            . ' WHERE ' . _DB_PREFIX_ . 'order_slip.id_order IN (' . implode(', ', $orderIds) . ')', true, false
        ),
    ];

    // 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['id'] = (int) $order['id'];
        $order['clinic_id'] = (int) $order['clinic_id'];
        $order['customer_id'] = (int) $order['customer_id'];
        $order['state'] = (int) $order['state'];
        $dt = \DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $order['invoice_date']);
        $order['invoice_date'] = $dt ? $dt->format(\DateTimeInterface::ATOM) : $order['invoice_date'];

        // 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 = '';
            if (!\is_array($elements)) {
                $elements = [];
            }
            foreach ($elements as $elementIndex => $element) {
                if ($element['order_id'] == $order['id']) {
                    // Nettoyage et formatage de l'objet
                    if ($name == 'products') {
                        $element = \array_merge($element, [
                            'category_id' => (int) $element['category_id'],
                            'quantity' => (int) $element['quantity'],
                        ]);
                    }

                    // 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 ']';
