<?php

declare(strict_types=1);

usesApiSuite();

it('lets customer booking sessions read their own customer attributes', function (): void {
    api_test_covers('GET /customer/attributes', 'customer-access');

    $session = api_fixtures()->createUserSession(['user']);
    api_fixtures()->addCustomerAttribute((int)$session['user']['id'], 'onlyTankCleaning');

    $response = api_client()->get(
        '/customer/attributes?customer_number=' . (int)$session['user']['customer_number'],
        $session['headers']
    );

    $response
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();

    $attributes = array_map(
        static fn(array $attribute): string => (string)($attribute['attribute'] ?? ''),
        is_array($response->data()) ? $response->data() : []
    );

    expect($attributes)->toContain('onlyTankCleaning');
    expect($response->body)->not->toContain('list_customer_attributes');
});

it('keeps customer attribute reads scoped to the authenticated customer', function (): void {
    api_test_covers('GET /customer/attributes', 'customer-access');

    $session = api_fixtures()->createUserSession(['user']);
    $otherCustomer = api_fixtures()->createUser(['display_name' => 'Other Attribute Customer']);
    api_fixtures()->addCustomerAttribute((int)$otherCustomer['id'], 'onlyTankCleaning');

    $response = api_client()->get(
        '/customer/attributes?customer_number=' . (int)$otherCustomer['customer_number'],
        $session['headers']
    );

    $response
        ->assertStatus(403)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMissingPermissions(['list_customer_attributes']);
});

it('still lets attribute managers read another customer attributes', function (): void {
    api_test_covers('GET /customer/attributes', 'permissions');

    $session = api_fixtures()->createUserSession(['list_customer_attributes']);
    $customer = api_fixtures()->createUser(['display_name' => 'Managed Attribute Customer']);
    api_fixtures()->addCustomerAttribute((int)$customer['id'], 'onlyTankCleaning');

    $response = api_client()->get(
        '/customer/attributes?customer_number=' . (int)$customer['customer_number'],
        $session['headers']
    );

    $response
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();

    $attributes = array_map(
        static fn(array $attribute): string => (string)($attribute['attribute'] ?? ''),
        is_array($response->data()) ? $response->data() : []
    );

    expect($attributes)->toContain('onlyTankCleaning');
});

it('returns exact product restrictions for product-impact attributes and null for workflow attributes', function (): void {
    api_test_covers('GET /customer/attributes', 'product_restrictions');

    $session = api_fixtures()->createUserSession(['list_customer_attributes']);
    $customer = api_fixtures()->createUser(['display_name' => 'Configured Attribute Customer']);
    api_fixtures()->addCustomerAttribute((int)$customer['id'], 'restrictSpotFree');
    api_fixtures()->addCustomerAttribute((int)$customer['id'], 'exemptFromAdministrationFee');
    $product = api_fixtures()->createProduct(['name' => 'Configured exact rinse']);

    new \classes\customer_rule_product_restriction_service();
    $db = api_test_runtime()->db();
    $collectionResult = $db->query(
        "SELECT id FROM customer_rule_product_collections
         WHERE attribute = 'restrictSpotFree' ORDER BY sort_order, id LIMIT 1"
    );
    $collectionId = (int)$collectionResult->fetch_assoc()['id'];
    $db->query(
        "INSERT IGNORE INTO customer_rule_product_collection_products (collection_id, product_id)
         VALUES ({$collectionId}, " . (int)$product['id'] . ')'
    );
    api_fixtures()->cleanupDeleteWhere('customer_rule_product_collection_products', [
        'collection_id' => $collectionId,
        'product_id' => (int)$product['id'],
    ]);

    $response = api_client()->get(
        '/customer/attributes?customer_number=' . (int)$customer['customer_number'],
        $session['headers']
    );
    $response->assertStatus(200)->assertEnvelope()->assertSuccess();

    $byAttribute = [];
    foreach ($response->data() as $attribute) {
        $byAttribute[(string)$attribute['attribute']] = $attribute;
    }
    expect($byAttribute['restrictSpotFree']['product_restriction']['disabled_product_ids'] ?? [])
        ->toContain((int)$product['id'])
        ->and($byAttribute['restrictSpotFree']['product_restriction']['collections'] ?? [])->not->toBeEmpty()
        ->and($byAttribute['exemptFromAdministrationFee'])->toHaveKey('product_restriction')
        ->and($byAttribute['exemptFromAdministrationFee']['product_restriction'])->toBeNull();
});

it('keeps workflow-only customer attribute activation compatible', function (): void {
    api_test_covers('POST /customer/attributes', 'workflow_compatibility');
    api_test_covers('DELETE /customer/attributes', 'workflow_compatibility');

    $session = api_fixtures()->createUserSession([
        'list_customer_attributes',
        'add_customer_attribute',
        'delete_customer_attribute',
    ]);
    $customer = api_fixtures()->createUser(['display_name' => 'Workflow Attribute Customer']);

    api_client()->post('/customer/attributes', [
        'user_id' => (int)$customer['id'],
        'attribute' => 'exemptFromAdministrationFee',
    ], $session['headers'])
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();

    $listed = api_client()->get(
        '/customer/attributes?customer_number=' . (int)$customer['customer_number'],
        $session['headers']
    );
    expect(array_column($listed->data(), 'attribute'))->toContain('exemptFromAdministrationFee');

    api_client()->delete(
        '/customer/attributes?user_id=' . (int)$customer['id'] . '&attribute=exemptFromAdministrationFee',
        null,
        $session['headers']
    )
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();
});
