<?php

declare(strict_types=1);

use classes\limited_backoffice_service;

usesApiSuite();

function department_customer_pricing_price_insert(int $departmentId, int $productId, int $price): void
{
    $statement = api_test_runtime()->db()->prepare(
        'INSERT INTO `product_department_prices` (`department_id`, `product_id`, `price`)
         VALUES (?, ?, ?)
         ON DUPLICATE KEY UPDATE `price` = VALUES(`price`)'
    );
    $statement->bind_param('iii', $departmentId, $productId, $price);
    $statement->execute();
    $statement->close();

    api_fixtures()->cleanupDeleteWhere('product_department_prices', [
        'department_id' => $departmentId,
        'product_id' => $productId,
    ]);
}

function department_customer_pricing_setup(array $departmentAttributes = []): array
{
    $department = api_fixtures()->createDepartment([
        'name' => 'Scoped Customer Pricing Department',
        'custom_pricing_only' => 1,
        ...$departmentAttributes,
    ]);
    $category = api_fixtures()->createCategory(['name' => 'Scoped Customer Pricing Category']);
    $product = api_fixtures()->createProduct([
        'name' => 'Scoped Customer Pricing Product',
        'category' => $category['id'],
        'price' => 1000,
        'apply_category_discount' => 1,
    ]);
    api_fixtures()->linkDepartmentCategory((int)$department['id'], (int)$category['id']);
    department_customer_pricing_price_insert((int)$department['id'], (int)$product['id'], 1000);
    $customer = api_fixtures()->createUser(['display_name' => 'Scoped Customer Pricing Customer']);

    return [
        'department' => $department,
        'category' => $category,
        'product' => $product,
        'customer' => $customer,
    ];
}

it('rejects department customer pricing when custom-only pricing is disabled', function (): void {
    api_test_covers('GET /superuser/department/customer-pricing', 'validation');

    $fixture = department_customer_pricing_setup(['custom_pricing_only' => 0]);
    $session = api_fixtures()->createUserSession(['superuser_fetch_department_customer_pricing']);

    $response = api_client()->get(
        '/superuser/department/customer-pricing?department_id=' . (int)$fixture['department']['id'] .
        '&user_id=' . (int)$fixture['customer']['id'],
        $session['headers']
    );

    $response
        ->assertStatus(409)
        ->assertEnvelope()
        ->assertSuccess(false);

    expect($response->data()['code'] ?? null)->toBe('department_customer_pricing_disabled');
});

it('sets and applies department-specific customer discounts without legacy fallback', function (): void {
    api_test_covers('GET /superuser/department/customer-pricing', 'happy');
    api_test_covers('PUT /superuser/department/customer-pricing', 'happy');
    api_test_covers('GET /products', 'pricing');

    $fixture = department_customer_pricing_setup();
    api_fixtures()->createPriceOverride([
        'user_id' => $fixture['customer']['id'],
        'is_category' => 0,
        'product_or_category_id' => (string)$fixture['product']['id'],
        'percentage' => 80,
    ]);

    $session = api_fixtures()->createUserSession([
        'superuser_fetch_department_customer_pricing',
        'superuser_set_department_customer_pricing',
        'list_products',
        'department_access_' . (int)$fixture['department']['id'],
    ]);

    $updated = api_client()->put('/superuser/department/customer-pricing', [
        'department_id' => $fixture['department']['id'],
        'user_id' => $fixture['customer']['id'],
        'overrides' => [
            [
                'is_category' => false,
                'product_or_category_id' => $fixture['product']['id'],
                'discount' => 25,
                'fixed_price' => null,
            ],
        ],
    ], $session['headers']);

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

    expect($updated->data()['overrides'][0]['percentage'] ?? null)->toBe(25);
    expect($updated->data()['categories'][0]['products'][0]['effective_price'] ?? null)->toBe(750);

    $byCustomerNumber = api_client()->get(
        '/superuser/department/customer-pricing?department_id=' . (int)$fixture['department']['id'] .
        '&customer_number=' . (int)$fixture['customer']['customer_number'],
        $session['headers']
    );
    $byCustomerNumber
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();
    expect($byCustomerNumber->data()['customer']['id'] ?? null)->toBe((int)$fixture['customer']['id']);

    $productResponse = api_client()->get(
        '/products?final_price=true&id=' . (int)$fixture['product']['id'] .
        '&department_id=' . (int)$fixture['department']['id'] .
        '&customer_id=' . (int)$fixture['customer']['customer_number'],
        $session['headers']
    );

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

    expect((int)($productResponse->data()['price'] ?? 0))->toBe(750);
});

it('limits department customer pricing to assigned limited-backoffice departments', function (): void {
    api_test_covers('GET /limited-backoffice/departments/{departmentId}/customer-pricing', 'auth');
    api_test_covers('PUT /limited-backoffice/departments/{departmentId}/customer-pricing', 'auth');

    $fixture = department_customer_pricing_setup();
    $otherFixture = department_customer_pricing_setup(['name' => 'Denied Scoped Customer Pricing Department']);
    $session = api_fixtures()->createUserSession([
        limited_backoffice_service::PERMISSION_ACCESS,
        limited_backoffice_service::PERMISSION_VIEW_CUSTOMER_PRICING,
        limited_backoffice_service::PERMISSION_MANAGE_CUSTOMER_PRICING,
        'department_access_' . (int)$fixture['department']['id'],
    ]);

    api_client()
        ->get(
            '/limited-backoffice/departments/' . (int)$fixture['department']['id'] .
            '/customer-pricing?user_id=' . (int)$fixture['customer']['id'],
            api_fixtures()->createUserSession([
                limited_backoffice_service::PERMISSION_ACCESS,
                'department_access_' . (int)$fixture['department']['id'],
            ])['headers']
        )
        ->assertStatus(403)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMissingPermissions([limited_backoffice_service::PERMISSION_VIEW_CUSTOMER_PRICING]);

    api_client()
        ->get(
            '/limited-backoffice/departments/' . (int)$otherFixture['department']['id'] .
            '/customer-pricing?user_id=' . (int)$otherFixture['customer']['id'],
            $session['headers']
        )
        ->assertStatus(403)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMissingPermissions(['department_access_' . (int)$otherFixture['department']['id']]);

    api_client()
        ->put(
            '/limited-backoffice/departments/' . (int)$fixture['department']['id'] . '/customer-pricing',
            [
                'user_id' => $fixture['customer']['id'],
                'overrides' => [],
            ],
            api_fixtures()->createUserSession([
                limited_backoffice_service::PERMISSION_ACCESS,
                limited_backoffice_service::PERMISSION_VIEW_CUSTOMER_PRICING,
                'department_access_' . (int)$fixture['department']['id'],
            ])['headers']
        )
        ->assertStatus(403)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMissingPermissions([limited_backoffice_service::PERMISSION_MANAGE_CUSTOMER_PRICING]);

    $updated = api_client()->put(
        '/limited-backoffice/departments/' . (int)$fixture['department']['id'] . '/customer-pricing',
        [
            'user_id' => $fixture['customer']['id'],
            'overrides' => [
                [
                    'is_category' => true,
                    'product_or_category_id' => (string)$fixture['category']['id'],
                    'discount' => 30,
                ],
            ],
        ],
        $session['headers']
    );

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

    expect($updated->data()['overrides'][0]['percentage'] ?? null)->toBe(30);
    expect($updated->data()['categories'][0]['products'][0]['effective_price'] ?? null)->toBe(700);
});
