<?php

app_require('classes/economic_v2_versioning_service.php');
app_require('classes/economic_v2_distribution_service.php');

use classes\economic_v2_distribution_service;
use classes\economic_v2_versioning_service;

if (!class_exists('FakeEconomicV2ProductFixedPriceVersioningService')) {
    class FakeEconomicV2ProductFixedPriceVersioningService extends economic_v2_versioning_service
    {
        public function __construct()
        {
        }

        public function resolveFixedPricingVersionAt(int $customer_number, string $timestamp): ?array
        {
            return null;
        }

        public function resolveVehicleSubscriptionVersionsAt(int $customer_number, string $timestamp): array
        {
            return [];
        }

        public function resolveDiscountOverrideAt(int $customer_number, bool $is_category, string|int $object_id, string $timestamp, ?int $department_id = null): ?array
        {
            if (!$is_category && (int)$object_id === 42) {
                return [
                    'customer_number' => $customer_number,
                    'is_category' => 0,
                    'object_id' => '42',
                    'discount' => 10,
                    'fixed_price' => 350,
                ];
            }

            if ($is_category) {
                return [
                    'customer_number' => $customer_number,
                    'is_category' => 1,
                    'object_id' => (string)$object_id,
                    'discount' => 80,
                    'fixed_price' => null,
                ];
            }

            return null;
        }

        public function runBestEffortBackfill(): array
        {
            return [];
        }
    }
}

if (!class_exists('TestableEconomicV2ProductFixedPriceDistributionService')) {
    class TestableEconomicV2ProductFixedPriceDistributionService extends economic_v2_distribution_service
    {
        public function __construct()
        {
            parent::__construct(new FakeEconomicV2ProductFixedPriceVersioningService());
        }

        public function exposeCalculateOrderOriginalPrice(array $order_items, int $customer_number, int $department_id, string $timestamp): float
        {
            return $this->calculateOrderOriginalPrice($order_items, $customer_number, $department_id, $timestamp);
        }

        protected function ensureVersionHistoryAvailable(array $areas): void
        {
        }

        protected function fetchOrdersInRange(string $from_ts, string $to_ts): array
        {
            return [[
                'id' => 1001,
                'customer_id' => 35131752,
                'department_id' => 7,
                'created_at' => '2026-01-05 12:00:00',
                'include_in_invoice' => 1,
            ]];
        }

        protected function fetchOrderItemsByOrderIds(array $order_ids): array
        {
            return [
                1001 => [[
                    'product_id' => 42,
                    'quantity' => 2,
                    'price' => 0,
                ]],
            ];
        }

        protected function getProductDepartmentPrice(int $product_id, int $department_id): float
        {
            return 1000.0;
        }

        protected function resolveDiscountForProduct(int $customer_number, int $product_id, string $timestamp, ?int $department_id = null): ?array
        {
            if ($product_id !== 42) {
                return null;
            }

            return [
                'customer_number' => $customer_number,
                'is_category' => 0,
                'object_id' => '42',
                'discount' => 10,
                'fixed_price' => 350,
            ];
        }

        protected function isOrderEligible(array $order): bool
        {
            return true;
        }

        protected function shouldIncludeCustomerNumber(int $customer_number): bool
        {
            return $customer_number > 0;
        }

        protected function parseDepartmentMap(array $department_map): array
        {
            $parsed = [];
            foreach ($department_map as $department_id => $amount) {
                $parsed['Department ' . $department_id] = round((float)$amount, 5);
            }
            return $parsed;
        }

        protected function buildCustomerEnvelope(int $customer_number, array $transaction_map): array
        {
            return [
                'id' => $customer_number,
                'customer_number' => $customer_number,
                'customer_name' => 'Customer ' . $customer_number,
                'transactions' => array_values($transaction_map),
                'requires_action' => false,
                'meta' => [],
            ];
        }

        protected function buildTransactionObject(int $order_id, string $created_at, int $department_id, ?float $amount = null, ?bool $included = null): array
        {
            return [
                'id' => $order_id,
                'date' => $created_at,
                'amount' => round((float)($amount ?? 0.0), 5),
                'booked' => true,
                'department_id' => $department_id,
                'excluded' => !($included ?? true),
            ];
        }
    }
}

it('uses product fixed prices before discounts in customer price distributions', function (): void {
    $service = new TestableEconomicV2ProductFixedPriceDistributionService();

    $result = $service->getCustomerPricesDistribution('2026-01-01', '2026-01-31');

    expect($result['collective_results']['total_discount_amount'])->toBe(1300.0);
    expect($result['collective_results']['department_discount_totals'][7])->toBe(1300.0);
    expect($result['customers'][0]['meta']['customer_prices']['discount_total'])->toBe(1300.0);
    expect($result['customers'][0]['transactions'][0]['amount'])->toBe(1300.0);

    expect($service->exposeCalculateOrderOriginalPrice(
        [[
            'product_id' => 42,
            'quantity' => 2,
            'price' => 0,
        ]],
        35131752,
        7,
        '2026-01-05 12:00:00'
    ))->toBe(700.0);
});
