<?php

app_require('routes/InvoicingPeriodRoute.php');

use routes\InvoicingPeriodRoute;

it('requires superuser permission for invoicing period distribution all endpoint', function (): void {
    $routeFile = app_path('routes/InvoicingPeriodRoute.php');
    $content = file_get_contents($routeFile);

    expect($content)->not->toBeFalse();
    expect($content)->toMatch(
        "/\\/superuser\\/invoicing\\/period\\/distribution\\/all'.*?\\\$this->requirePermission\\('superuser_invoicing_period'\\);/s"
    );
});

it('uses shared date-range normalization across invoicing period endpoints', function (): void {
    $routeFile = app_path('routes/InvoicingPeriodRoute.php');
    $content = file_get_contents($routeFile);

    expect($content)->not->toBeFalse();
    expect(substr_count((string)$content, 'requireAndNormalizeDateRange()'))->toBeGreaterThanOrEqual(5);
});

it('keeps the main period response local-only for booked state and customer names', function (): void {
    $routeFile = app_path('routes/InvoicingPeriodRoute.php');
    $content = file_get_contents($routeFile);

    expect($content)->not->toBeFalse();
    $content = (string)$content;

    expect($content)->not->toContain('isBooked(true)')
        ->and($content)->toContain('isTransactionBookedFromLocalState($transaction)')
        ->and($content)->toContain('SELECT booked_invoice_id FROM collected_order_invoices')
        ->and($content)->toContain('SELECT invoice_id FROM economic_module_orders')
        ->and($content)->toContain('getCustomerNames(array_keys($customer_numbers), false)')
        ->and($content)->toContain('getCustomerNames(array_map(\'intval\', $customer_numbers), false)');
});

it('streams the main period response instead of encoding the full payload at once', function (): void {
    $routeFile = app_path('routes/InvoicingPeriodRoute.php');
    $content = file_get_contents($routeFile);

    expect($content)->not->toBeFalse();
    $content = (string)$content;

    expect($content)->toContain('private static function streamInvoicingPeriodResponse(array $period): void')
        ->and($content)->toContain("\$includeInvoicePeriodFlags = \$this->hasPermission('list_invoice_period_flags');")
        ->and($content)->toContain('$period = self::getInvoicingPeriod($dateFrom, $dateTo, $customerNumbers, $includeInvoicePeriodFlags);')
        ->and($content)->toContain('self::streamInvoicingPeriodResponse($period);')
        ->and($content)->not->toContain('$response->success([' . PHP_EOL . '                    ...self::getInvoicingPeriod($dateFrom, $dateTo, $customerNumbers)')
        ->and($content)->toContain('echo self::jsonFragment($customer);');
});

it('only includes invoice period flags when the list permission is granted', function (): void {
    $content = file_get_contents(app_path('routes/InvoicingPeriodRoute.php'));

    expect($content)->not->toBeFalse();
    $content = (string)$content;

    expect($content)
        ->toContain("\$includeInvoicePeriodFlags = \$this->hasPermission('list_invoice_period_flags');")
        ->and($content)->toContain('bool $includeInvoicePeriodFlags = false')
        ->and($content)->toContain('if ($includeInvoicePeriodFlags) {')
        ->and($content)->toContain('applyFlagsToPeriodTypes(');
});

it('maps batched period transaction rows to the legacy transaction response shape', function (): void {
    $reflection = new ReflectionClass(InvoicingPeriodRoute::class);
    $method = $reflection->getMethod('constructTransactionObjectFromPeriodRow');

    $transaction = $method->invokeArgs(null, [[
        'id' => '42',
        'created_at' => '2026-04-10 12:34:56',
        'net_amount' => '123.50',
        'booked' => '1',
        'department_id' => '7',
        'customer_id' => '27983',
        'order_reference' => 'REF-42',
        'order_po' => 'PO-42',
        'order_notes' => 'Driver note',
        'reg_1' => 'AB12345',
        'reg_2' => 'CD67890',
        'reg_3' => '',
        'invoice_collection_id' => '314',
        'include_in_invoice_effective' => '0',
    ]]);

    expect($transaction)->toMatchArray([
        'id' => 42,
        'date' => '2026-04-10 12:34:56',
        'amount' => 123.5,
        'booked' => true,
        'department_id' => 7,
        'customer_number' => 27983,
        'reference' => 'REF-42',
        'po' => 'PO-42',
        'notes' => 'Driver note',
        'reg_1' => 'AB12345',
        'reg_2' => 'CD67890',
        'reg_3' => '',
        'excluded' => true,
        'invoice_collection_id' => 314,
        'queue_status' => null,
        'queue_job_id' => null,
    ]);
});

it('uses batched period transactions and keyed customer maps in the main period route', function (): void {
    $content = file_get_contents(app_path('routes/InvoicingPeriodRoute.php'));

    expect($content)->not->toBeFalse();
    $content = (string)$content;

    expect($content)->toContain('getPeriodTransactionsForCustomersInDateRange(')
        ->and($content)->toContain('private static function indexCustomersByNumber(array $customers): array')
        ->and($content)->toContain('$customers_by_number = self::indexCustomersByNumber($customersWithTransactions);')
        ->and($content)->toContain('invoicing_period_utils::filterPossibleDuplicates($ordersByRegistration, 86400)')
        ->and($content)->not->toContain('getOrdersWithPossibleDuplicates($dateFrom, $dateTo)');
});

it('falls back to configured e-conomic default department for missing customer default department in distributions', function (): void {
    $content = file_get_contents(app_path('routes/InvoicingPeriodRoute.php'));

    expect($content)->not->toBeFalse();
    $content = (string)$content;

    expect($content)
        ->toContain('private static function getEconomicFallbackDepartmentId(): int')
        ->and($content)->toContain('(new economic())->getDefaultDistributionDepartmentId()')
        ->and($content)->toContain(': self::getEconomicFallbackDepartmentId();')
        ->and($content)->toContain("\$department_totals[\$fallback_department_id] = (float)\$customer['meta']['fixed_pricing']['price'];");
});
