<?php

app_require('routes/InvoicingPeriodRoute.php');

use routes\InvoicingPeriodRoute;

function invoicing_period_queue_overlay_invoke(string $method, array $args = []): mixed
{
    $reflection = new ReflectionClass(InvoicingPeriodRoute::class);
    $target = $reflection->getMethod($method);
    return $target->invokeArgs(null, $args);
}

function invoicing_period_queue_overlay_job(
    int $queue_job_id,
    string $queue_status,
    int $invoice_collection_id,
    int $customer_number,
    bool $is_period_relevant = true
): array {
    return [
        'queue_job_id' => $queue_job_id,
        'queue_status' => $queue_status,
        'invoice_collection_id' => $invoice_collection_id,
        'customer_number' => $customer_number,
        'created_at' => '2026-04-01 00:00:01',
        'closed_at' => '2026-04-01 00:00:01',
        'is_period_relevant' => $is_period_relevant,
    ];
}

it('marks queued transactions and clears requires_action when all actionable work is already queued', function (): void {
    $queueJob = invoicing_period_queue_overlay_job(93, 'QUEUED', 14578, 42424242);

    $customer = [
        'customer_number' => 42424242,
        'customer_name' => 'Queue Customer',
        'requires_action' => true,
        'transactions' => [
            [
                'id' => 501,
                'booked' => false,
                'excluded' => false,
                'invoice_collection_id' => 14578,
                'queue_status' => null,
                'queue_job_id' => null,
            ],
        ],
    ];

    $result = invoicing_period_queue_overlay_invoke('applyCollectedInvoiceQueueOverlayToCustomer', [
        $customer,
        [14578 => $queueJob],
        [42424242 => [$queueJob]],
    ]);

    expect($result['requires_action'])->toBeFalse();
    expect($result['transactions'][0]['queue_status'])->toBe('QUEUED');
    expect($result['transactions'][0]['queue_job_id'])->toBe(93);
    expect($result['queue'])->toBe([
        'has_active_job' => true,
        'statuses' => ['QUEUED'],
        'invoice_collection_ids' => [14578],
        'is_action_blocked' => true,
    ]);
});

it('keeps requires_action true when a customer still has unqueued actionable transactions', function (): void {
    $queueJob = invoicing_period_queue_overlay_job(94, 'PROCESSING', 2001, 43434343);

    $customer = [
        'customer_number' => 43434343,
        'customer_name' => 'Mixed Customer',
        'requires_action' => true,
        'transactions' => [
            [
                'id' => 601,
                'booked' => false,
                'excluded' => false,
                'invoice_collection_id' => 2001,
                'queue_status' => null,
                'queue_job_id' => null,
            ],
            [
                'id' => 602,
                'booked' => false,
                'excluded' => false,
                'invoice_collection_id' => null,
                'queue_status' => null,
                'queue_job_id' => null,
            ],
        ],
    ];

    $result = invoicing_period_queue_overlay_invoke('applyCollectedInvoiceQueueOverlayToCustomer', [
        $customer,
        [2001 => $queueJob],
        [43434343 => [$queueJob]],
    ]);

    expect($result['requires_action'])->toBeTrue();
    expect($result['transactions'][0]['queue_status'])->toBe('PROCESSING');
    expect($result['transactions'][1]['queue_status'])->toBeNull();
    expect($result['queue'])->toBe([
        'has_active_job' => true,
        'statuses' => ['PROCESSING'],
        'invoice_collection_ids' => [2001],
        'is_action_blocked' => false,
    ]);
});

it('blocks fixed-pricing or subscription customers with no transactions when a relevant queue job exists', function (): void {
    $queueJob = invoicing_period_queue_overlay_job(95, 'QUEUED', 3001, 45454545, true);

    $customer = [
        'customer_number' => 45454545,
        'customer_name' => 'Subscription Customer',
        'requires_action' => true,
        'transactions' => [],
        'meta' => [
            'fixed_pricing' => [
                'price' => 1200,
            ],
        ],
    ];

    $result = invoicing_period_queue_overlay_invoke('applyCollectedInvoiceQueueOverlayToCustomer', [
        $customer,
        [],
        [45454545 => [$queueJob]],
    ]);

    expect($result['requires_action'])->toBeFalse();
    expect($result['queue'])->toBe([
        'has_active_job' => true,
        'statuses' => ['QUEUED'],
        'invoice_collection_ids' => [3001],
        'is_action_blocked' => true,
    ]);
});

it('normalizes targeted customer number filters from comma-separated or repeated values', function (): void {
    expect(invoicing_period_queue_overlay_invoke('normalizeCustomerNumbers', [
        '42424242, 43434343,42424242,0,not-a-number',
    ]))->toBe([42424242, 43434343]);

    expect(invoicing_period_queue_overlay_invoke('normalizeCustomerNumbers', [
        ['45454545', 45454545, '46464646'],
    ]))->toBe([45454545, 46464646]);
});

it('filters period customer number candidates to targeted customers only', function (): void {
    $result = invoicing_period_queue_overlay_invoke('filterCustomerNumbers', [
        [42424242, '43434343', 45454545],
        [43434343, 99999999],
    ]);

    expect($result)->toBe([43434343]);
});
