<?php

declare(strict_types=1);

usesApiSuite();

it('requires classic superuser view and manage permissions for global rule configuration', function (): void {
    api_test_covers('GET /superuser/customer-rules/product-restrictions', 'permissions');
    api_test_covers('PUT /superuser/customer-rules/product-restrictions/{attribute}', 'permissions');

    $withoutView = api_fixtures()->createUserSession(['superuser']);
    api_client()->get('/superuser/customer-rules/product-restrictions', $withoutView['headers'])
        ->assertStatus(403)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMissingPermissions(['superuser_customer_rules_view']);

    $viewOnly = api_fixtures()->createUserSession(['superuser', 'superuser_customer_rules_view']);
    $configuration = api_client()->get('/superuser/customer-rules/product-restrictions', $viewOnly['headers']);
    $configuration->assertStatus(200)->assertEnvelope()->assertSuccess();
    expect($configuration->data()['rules'] ?? [])->toHaveCount(5)
        ->and($configuration->data()['products'] ?? null)->toBeArray();

    $rule = $configuration->data()['rules'][0];
    api_client()->put(
        '/superuser/customer-rules/product-restrictions/' . $rule['attribute'],
        ['version' => $rule['version'], 'collections' => $rule['collections']],
        $viewOnly['headers']
    )
        ->assertStatus(403)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMissingPermissions(['superuser_customer_rules_manage']);

    $manageOnly = api_fixtures()->createUserSession(['superuser', 'superuser_customer_rules_manage']);
    api_client()->get('/superuser/customer-rules/product-restrictions', $manageOnly['headers'])
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();
});

it('atomically replaces collections and rejects stale versions and invalid products', function (): void {
    api_test_covers('PUT /superuser/customer-rules/product-restrictions/{attribute}', 'versioned_atomic_replace');

    $session = api_fixtures()->createUserSession([
        'superuser',
        'superuser_customer_rules_view',
        'superuser_customer_rules_manage',
    ]);
    $product = api_fixtures()->createProduct(['name' => 'Managed exact customer-rule product']);
    $get = api_client()->get('/superuser/customer-rules/product-restrictions', $session['headers']);
    $rules = $get->data()['rules'];
    $rule = array_values(array_filter(
        $rules,
        static fn(array $candidate): bool => $candidate['attribute'] === 'restrictInteriorCleaning'
    ))[0];
    $collectionName = 'API managed ' . bin2hex(random_bytes(5));
    $collections = $rule['collections'];
    $collections[] = [
        'name' => $collectionName,
        'sort_order' => 999,
        'product_ids' => [(int)$product['id']],
    ];

    $saved = api_client()->put(
        '/superuser/customer-rules/product-restrictions/restrictInteriorCleaning',
        ['version' => $rule['version'], 'collections' => $collections],
        $session['headers']
    );
    $saved->assertStatus(200)->assertEnvelope()->assertSuccess();
    expect($saved->data()['version'])->toBe((int)$rule['version'] + 1)
        ->and($saved->data()['disabled_product_ids'])->toContain((int)$product['id']);

    $managedCollection = array_values(array_filter(
        $saved->data()['collections'],
        static fn(array $collection): bool => $collection['name'] === $collectionName
    ))[0];
    $collectionId = (int)$managedCollection['id'];

    try {
        api_client()->put(
            '/superuser/customer-rules/product-restrictions/restrictInteriorCleaning',
            ['version' => $rule['version'], 'collections' => $collections],
            $session['headers']
        )
            ->assertStatus(409)
            ->assertEnvelope()
            ->assertSuccess(false)
            ->assertMessage('Customer rule configuration has changed; reload before saving');

        $invalidCollections = $saved->data()['collections'];
        $invalidCollections[0]['product_ids'][] = 2147483647;
        api_client()->put(
            '/superuser/customer-rules/product-restrictions/restrictInteriorCleaning',
            ['version' => $saved->data()['version'], 'collections' => $invalidCollections],
            $session['headers']
        )
            ->assertStatus(422)
            ->assertEnvelope()
            ->assertSuccess(false);

        $unchanged = api_client()->get('/superuser/customer-rules/product-restrictions', $session['headers']);
        $current = array_values(array_filter(
            $unchanged->data()['rules'],
            static fn(array $candidate): bool => $candidate['attribute'] === 'restrictInteriorCleaning'
        ))[0];
        expect($current['version'])->toBe($saved->data()['version'])
            ->and($current['disabled_product_ids'])->not->toContain(2147483647);
    } finally {
        $db = api_test_runtime()->db();
        $db->query("DELETE FROM customer_rule_product_collection_products WHERE collection_id = {$collectionId}");
        $db->query("DELETE FROM customer_rule_product_collections WHERE id = {$collectionId}");
        $db->query(
            "UPDATE customer_rule_product_restrictions SET version = " . (int)$rule['version'] .
            " WHERE attribute = 'restrictInteriorCleaning'"
        );
    }
});
