<?php

namespace classes;

use InvalidArgumentException;

class invoicing_period_utils
{
    /**
     * Normalize date range for invoicing endpoints to full-day timestamps.
     *
     * @return array{dateFrom:string,dateTo:string}
     */
    public static function normalizeDateRange(string $dateFrom, string $dateTo): array
    {
        if (!self::isValidDate($dateFrom)) {
            throw new InvalidArgumentException('Invalid date format. Expected: Y-m-d Got: ' . $dateFrom);
        }
        if (!self::isValidDate($dateTo)) {
            throw new InvalidArgumentException('Invalid date format. Expected: Y-m-d Got: ' . $dateTo);
        }

        if (strtotime($dateFrom) === false || strtotime($dateTo) === false) {
            throw new InvalidArgumentException('Invalid date range provided');
        }

        if (strtotime($dateFrom) > strtotime($dateTo)) {
            throw new InvalidArgumentException('Invalid date range. dateFrom must be before or equal to dateTo');
        }

        return [
            'dateFrom' => date('Y-m-d 00:00:00', strtotime($dateFrom)),
            'dateTo' => date('Y-m-d 23:59:59', strtotime($dateTo)),
        ];
    }

    /**
     * Filter grouped orders down to orders that have at least one neighbor within the time window.
     *
     * @param array<string, array<int, array<string,mixed>>> $ordersByRegistration
     * @return array<string, array<int, array<string,mixed>>>
     */
    public static function filterPossibleDuplicates(array $ordersByRegistration, int $windowSeconds = 86400): array
    {
        $possibleDuplicates = [];

        foreach ( $ordersByRegistration as $registration => $orderList ) {
            if (count($orderList) < 2) {
                continue;
            }

            $normalizedOrders = [];
            foreach ( $orderList as $order ) {
                $createdAt = (string)($order['created_at'] ?? '');
                $timestamp = strtotime($createdAt);
                if ($timestamp === false) {
                    continue;
                }
                $order['_timestamp'] = $timestamp;
                $normalizedOrders[] = $order;
            }

            if (count($normalizedOrders) < 2) {
                continue;
            }

            usort($normalizedOrders, function (array $a, array $b) {
                return (int)$a['_timestamp'] <=> (int)$b['_timestamp'];
            });

            $duplicateIndexes = [];
            $count = count($normalizedOrders);
            for ( $i = 0; $i < $count; $i++ ) {
                $currentTimestamp = (int)$normalizedOrders[$i]['_timestamp'];
                for ( $j = $i - 1; $j >= 0; $j-- ) {
                    $delta = $currentTimestamp - (int)$normalizedOrders[$j]['_timestamp'];
                    if ($delta > $windowSeconds) {
                        break;
                    }
                    $duplicateIndexes[$i] = true;
                    $duplicateIndexes[$j] = true;
                }
            }

            if (count($duplicateIndexes) < 2) {
                continue;
            }

            $possibleDuplicates[$registration] = [];
            $indexes = array_keys($duplicateIndexes);
            sort($indexes);
            foreach ( $indexes as $index ) {
                $order = $normalizedOrders[$index];
                unset($order['_timestamp']);
                $possibleDuplicates[$registration][] = $order;
            }
        }

        return $possibleDuplicates;
    }

    private static function isValidDate(string $date): bool
    {
        $parsed = \DateTime::createFromFormat('Y-m-d', $date);
        return $parsed !== false && $parsed->format('Y-m-d') === $date;
    }
}
