<?php

declare(strict_types=1);

require_once __DIR__ . '/reporting_init.php';

use Myvetshop\Module\Clinique\Serializer\OrderReportingSerializer;

// Constantes
define('ORDERS_REQUEST_RESULTS_LIMIT', 1000);

// 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');
    echo 'Cannot parse date parameters';
    exit(0);
}

// On limite le nombre de jours pour éviter la surcharge de données
$diff = $dateMin->diff($dateMax);
if ($diff->invert) {
    header('HTTP/1.1 400 Bad Request');
    echo 'datemax have to be later than datemin';
    exit(0);
}
if ($diff->format('%a') > 100) {
    header('HTTP/1.1 400 Bad Request');
    echo 'Cannot get more than 100 days data';
    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_ . 'order_invoice ON ' . _DB_PREFIX_ . 'orders.id_order=' . _DB_PREFIX_ . 'order_invoice.id_order AND ' . _DB_PREFIX_ . 'order_invoice.number <> 0'
    . ' 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_ . 'order_invoice.date_add >= "' . $dateMin->format('Y-m-d H:i:s') . '"'
    . ' AND ' . _DB_PREFIX_ . 'order_invoice.date_add <= "' . $dateMax->format('Y-m-d H:i:s') . '"'
    . ' ORDER BY ' . _DB_PREFIX_ . 'order_invoice.date_add 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
$serializer = new OrderReportingSerializer();
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_ . 'order_invoice.date_add as invoice_date'
        . ', ' . _DB_PREFIX_ . Clinique::TABLE . '.id_' . Clinique::TABLE . ' as clinic_id'
        . ', ' . _DB_PREFIX_ . Clinique::TABLE . '.centrale as supplier'
        . ', ' . _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));

    $products = $db->executeS(
        'SELECT'
        . ' od.product_id as "id"'
        . ', od.id_order as "order_id"'
        . ', COALESCE(ps.product_supplier_reference,od.product_supplier_reference) as "supplier_code"'
        . ', pl.name as "name"'
        . ', al.name as "format"'
        . ', s.id_category_default as "category_id"'
        . ', p.id_manufacturer as "manufacturer_id"'
        . ', od.product_quantity as "quantity"'
        . ', od.purchase_supplier_price as "purchase_price"'
        . ', od.total_price_tax_excl as "total_price_tax_excl"'
        . ', od.total_price_tax_incl as "total_price_tax_incl"'
        . ' FROM ' . _DB_PREFIX_ . 'order_detail od'
        . ' LEFT JOIN ' . _DB_PREFIX_ . 'orders o ON o.id_order=od.id_order'
        . ' LEFT JOIN ' . _DB_PREFIX_ . Clinique::TABLE . ' c ON o.id_carrier=c.id_carrier OR o.id_carrier=c.id_carrier_home'
        . ' LEFT JOIN ' . _DB_PREFIX_ . 'myvetshop_warehouse_supplier ws ON ws.id_warehouse=c.id_warehouse'
        . ' LEFT JOIN ' . _DB_PREFIX_ . 'product p ON p.id_product=od.product_id'
        . ' LEFT JOIN ' . _DB_PREFIX_ . 'product_supplier ps ON ps.id_product=od.product_id AND ps.id_product_attribute=od.product_attribute_id AND ps.id_supplier=ws.id_supplier'
        . ' LEFT JOIN ' . _DB_PREFIX_ . 'product_shop s ON s.id_product=od.product_id AND s.id_shop=1'

        // Nom et format de produit
        . ' INNER JOIN ' . _DB_PREFIX_ . 'product_lang pl ON pl.id_product=od.product_id AND pl.id_lang=1 AND pl.id_shop=1'
        . ' INNER JOIN ' . _DB_PREFIX_ . 'product_attribute_combination ac ON ac.id_product_attribute=od.product_attribute_id'
        . ' INNER JOIN ' . _DB_PREFIX_ . 'attribute_lang al ON al.id_attribute=ac.id_attribute AND al.id_lang=1'

        . ' WHERE od.id_order IN (' . implode(', ', $orderIds) . ')'
        . 'GROUP BY od.id_order_detail',
        true,
        false
    );

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

    $discounts = $db->executeS(
        'SELECT'
        . ' ocr.id_cart_rule as "id"'
        . ', ocr.id_order as "order_id"'
        . ', ocr.value_tax_excl as "value_tax_excl"'
        . ', ocr.value as "value_tax_incl"'
        . ' FROM ' . _DB_PREFIX_ . 'order_cart_rule ocr'
        . ' WHERE ocr.id_order IN (' . implode(', ', $orderIds) . ')',
        true,
        false
    );
    if (!\is_array($discounts)) {
        $discounts = [];
    }

    $refunds = $db->executeS(
        'SELECT'
        . ' os.id_order_slip as "id"'
        . ', os.id_order as "order_id"'
        . ', os.total_products_tax_excl as "total_products_tax_excl"'
        . ', os.total_products_tax_incl as "total_products_tax_incl"'
        . ', os.total_shipping_tax_excl as "total_shipping_tax_excl"'
        . ', os.total_shipping_tax_incl as "total_shipping_tax_incl"'
        . ' FROM ' . _DB_PREFIX_ . 'order_slip os'
        . ' WHERE os.id_order IN (' . implode(', ', $orderIds) . ')',
        true,
        false
    );
    if (!\is_array($refunds)) {
        $refunds = [];
    }

    $orders = OrderReportingSerializer::prepareOrdersArray(
        $orders,
        $products,
        $discounts,
        $refunds,
    );

    echo trim($serializer->serialize($orders), '[]');
}

// Fermeture du tableau json
echo ']';
