<?php

use classes\xlvask_automation_service;

require_once WD . '/classes/xlvask_automation_service.php';

it('normalizes registrations for XL Vask automation signatures', function (): void {
    expect(xlvask_automation_service::normalizeRegistrationForAutomation(' ec 21-233 '))
        ->toBe('EC21233');
});

it('builds stable XL Vask automation item signatures', function (): void {
    $items = [
        ['product_id' => 20, 'quantity' => 1, 'price' => 275],
        ['product_id' => 10, 'quantity' => 2, 'price' => 649],
        ['product_id' => 20, 'quantity' => 1, 'price' => 0],
    ];

    expect(xlvask_automation_service::itemSignaturePartsForAutomation($items))
        ->toBe([
            '10:2:649',
            '20:1:0',
            '20:1:275',
        ]);
});

it('identifies strict price agreement matches by product, quantity, and total', function (): void {
    $usageItems = [
        ['product_id' => 10, 'quantity' => 1, 'price' => 519],
        ['product_id' => 24, 'quantity' => 1, 'price' => 39],
        ['product_id' => 21, 'quantity' => 1, 'price' => 79],
    ];
    $orderItems = [
        ['product_id' => 21, 'quantity' => 1, 'price' => 79],
        ['product_id' => 10, 'quantity' => 1, 'price' => 519],
        ['product_id' => 24, 'quantity' => 1, 'price' => 39],
    ];

    expect(xlvask_automation_service::isExactItemMatchForAutomation($usageItems, $orderItems))
        ->toBeTrue();
});

it('rejects price agreement automation when product lines differ despite equal total', function (): void {
    $usageItems = [
        ['product_id' => 10, 'quantity' => 1, 'price' => 519],
        ['product_id' => 24, 'quantity' => 1, 'price' => 39],
    ];
    $orderItems = [
        ['product_id' => 10, 'quantity' => 1, 'price' => 519],
        ['product_id' => 50, 'quantity' => 1, 'price' => 39],
    ];

    expect(xlvask_automation_service::itemsTotalForAutomation($usageItems))
        ->toBe(xlvask_automation_service::itemsTotalForAutomation($orderItems))
        ->and(xlvask_automation_service::isExactItemMatchForAutomation($usageItems, $orderItems))
        ->toBeFalse();
});

it('normalizes persisted XL Vask usage-log rows before helper hydration', function (): void {
    $row = xlvask_automation_service::normalizeUsageLogRowForAutomation([
        'id' => 47086,
        'WashId' => 'cc1eabc1-b4e1-425b-ad7c-dc68f8c97ceb',
        'WashItems' => '[{"OriginalProductName":"Bus","Count":1}]',
    ]);

    expect($row)
        ->not->toHaveKey('id')
        ->and($row['WashItems'])->toBe([
            [
                'OriginalProductName' => 'Bus',
                'Count' => 1,
            ],
        ]);
});

it('builds stable OpenAI cache keys for identical automation input', function (): void {
    $prompt = 'Prompt';
    $schemaName = 'xlvask_automation';
    $schema = [
        'required' => ['action'],
        'properties' => [
            'confidence' => ['type' => 'number'],
            'action' => ['type' => 'string'],
        ],
    ];
    $schemaWithDifferentKeyOrder = [
        'properties' => [
            'action' => ['type' => 'string'],
            'confidence' => ['type' => 'number'],
        ],
        'required' => ['action'],
    ];
    $payloadA = [
        'usage_log' => [
            'registration' => 'AB12345',
            'creation_allowed' => true,
        ],
        'candidate_orders' => [
            ['id' => 10, 'items' => [['product_id' => 1, 'quantity' => 1, 'price' => 100]]],
        ],
    ];
    $payloadB = [
        'candidate_orders' => [
            ['items' => [['price' => 100, 'quantity' => 1, 'product_id' => 1]], 'id' => 10],
        ],
        'usage_log' => [
            'creation_allowed' => true,
            'registration' => 'AB12345',
        ],
    ];

    expect(xlvask_automation_service::openAiCacheKeyForAutomation($schemaName, $prompt, $payloadA, $schema, 0.1))
        ->toBe(xlvask_automation_service::openAiCacheKeyForAutomation($schemaName, $prompt, $payloadB, $schemaWithDifferentKeyOrder, 0.1));
});

it('changes OpenAI cache keys when automation eligibility input changes', function (): void {
    $schema = ['type' => 'object'];
    $newerWashPayload = ['usage_log' => ['creation_allowed' => false, 'age_bucket' => 'newer_than_6_hours']];
    $olderWashPayload = ['usage_log' => ['creation_allowed' => true, 'age_bucket' => 'older_than_6_hours']];

    expect(xlvask_automation_service::openAiCacheKeyForAutomation('xlvask_automation', 'Prompt', $newerWashPayload, $schema, 0.1))
        ->not->toBe(xlvask_automation_service::openAiCacheKeyForAutomation('xlvask_automation', 'Prompt', $olderWashPayload, $schema, 0.1));
});

it('declares a persistent OpenAI cache table for XL Vask automation', function (): void {
    $bootstrapContent = file_get_contents(WD . '/classes/xlvask_usage_logs_schema_bootstrap.php');

    expect($bootstrapContent)
        ->toContain('xlvask_automation_openai_cache')
        ->toContain('UNIQUE KEY `uniq_xlvask_openai_cache_key` (`cache_key`)');
});

it('declares cached amount summary columns for XL Vask usage logs', function (): void {
    $bootstrapContent = file_get_contents(WD . '/classes/xlvask_usage_logs_schema_bootstrap.php');

    expect($bootstrapContent)
        ->toContain('cached_total_net_amount')
        ->toContain('cached_primary_product_name')
        ->toContain('cached_amount_at');
});

it('keeps automatic XL Vask execution scoped to exact attachments', function (): void {
    $serviceContent = file_get_contents(WD . '/classes/xlvask_automation_service.php');

    expect($serviceContent)
        ->toContain('&& $this->isExactAttachSuggestionForContext($suggestion, $context)')
        ->toContain("\$candidateOrderJson = \$suggestion['candidate_order_json'] ?? null;")
        ->toContain("return 'Automatisk accepteret: Prisoverensstemmelse.';");
});

it('does not automatically create XL Vask orders', function (): void {
    $serviceContent = file_get_contents(WD . '/classes/xlvask_automation_service.php');

    expect($serviceContent)
        ->toContain('if ($action === self::ACTION_CREATE) {')
        ->toContain('return false;');
});

it('scores same-day orders with matching XL Vask products and extra add-ons as attach suggestions', function (): void {
    $usageItems = [
        ['product_id' => 10, 'quantity' => 1, 'price' => 519, 'product' => ['name' => 'Forvogn']],
        ['product_id' => 24, 'quantity' => 1, 'price' => 39, 'product' => ['name' => 'Spot Free- Lastbil']],
        ['product_id' => 21, 'quantity' => 1, 'price' => 79, 'product' => ['name' => 'Undervognskyl pr. Enhed']],
        ['product_id' => 99, 'quantity' => 8, 'price' => 0, 'product' => ['name' => 'Halleje']],
    ];
    $orderItems = [
        ['product_id' => 10, 'quantity' => 1, 'price' => 519, 'product' => ['name' => 'Forvogn']],
        ['product_id' => 50, 'quantity' => 1, 'price' => 319, 'product' => ['name' => 'Indvendig vask Forvogn']],
        ['product_id' => 21, 'quantity' => 1, 'price' => 79, 'product' => ['name' => 'Undervognskyl pr. Enhed']],
        ['product_id' => 24, 'quantity' => 1, 'price' => 39, 'product' => ['name' => 'Spot Free- Lastbil']],
    ];

    $score = xlvask_automation_service::scoreItemMatchForAutomation($usageItems, $orderItems);

    expect($score['source'])
        ->toBe('fuzzy')
        ->and($score['confidence'])->toBeGreaterThanOrEqual(0.70)
        ->and($score['confidence'])->toBeLessThan(0.92)
        ->and($score['reason'])->toContain('ekstra ydelser');
});

it('does not score an order with only the primary product as a matching add-on attachment', function (): void {
    $usageItems = [
        ['product_id' => 10, 'quantity' => 1, 'price' => 519, 'product' => ['name' => 'Forvogn']],
        ['product_id' => 24, 'quantity' => 1, 'price' => 39, 'product' => ['name' => 'Spot Free- Lastbil']],
        ['product_id' => 21, 'quantity' => 1, 'price' => 79, 'product' => ['name' => 'Undervognskyl pr. Enhed']],
    ];
    $orderItems = [
        ['product_id' => 10, 'quantity' => 1, 'price' => 519, 'product' => ['name' => 'Forvogn']],
        ['product_id' => 50, 'quantity' => 1, 'price' => 319, 'product' => ['name' => 'Indvendig vask Forvogn']],
    ];

    expect(xlvask_automation_service::scoreItemMatchForAutomation($usageItems, $orderItems)['confidence'])
        ->toBe(0.0);
});
