<?php

declare(strict_types=1);

usesApiSuite();

function bulk_action_order_item_deleted_at(int $orderItemId): ?string
{
    $row = api_test_runtime()->queryOne('SELECT deleted_at FROM order_items WHERE id = ' . $orderItemId . ' LIMIT 1');
    return $row['deleted_at'] ?? null;
}

function bulk_action_order_invoice_collection_id(int $orderId): int
{
    $row = api_test_runtime()->queryOne('SELECT invoice_collection_id FROM orders WHERE id = ' . $orderId . ' LIMIT 1');
    return (int)($row['invoice_collection_id'] ?? 0);
}

function bulk_action_configure_rule_product(string $attribute, int $productId): void
{
    new \classes\customer_rule_product_restriction_service();
    $db = api_test_runtime()->db();
    $safeAttribute = $db->real_escape_string($attribute);
    $result = $db->query(
        "SELECT id FROM customer_rule_product_collections WHERE attribute = '{$safeAttribute}' ORDER BY sort_order, id LIMIT 1"
    );
    $collectionId = (int)$result->fetch_assoc()['id'];
    $db->query(
        "INSERT IGNORE INTO customer_rule_product_collection_products (collection_id, product_id)
         VALUES ({$collectionId}, {$productId})"
    );
    api_fixtures()->cleanupDeleteWhere('customer_rule_product_collection_products', [
        'collection_id' => $collectionId,
        'product_id' => $productId,
    ]);
}

it('previews and applies customer rule cleanup only after exact typed confirmation', function (): void {
    api_test_covers('POST /collected-invoices/bulk-actions/preview', 'customer-rule-cleanup');
    api_test_covers('POST /collected-invoices/bulk-actions/apply', 'customer-rule-cleanup');

    $customer = api_fixtures()->createUser(['display_name' => 'Bulk Cleanup Customer']);
    api_fixtures()->addCustomerAttribute((int)$customer['id'], 'restrictSpotFree');
    $department = api_fixtures()->createDepartment();
    $invoiceCollection = api_fixtures()->createInvoiceCollection([
        'customer_number' => $customer['customer_number'],
    ]);
    $order = api_fixtures()->createOrder([
        'customer_id' => $customer['customer_number'],
        'department_id' => $department['id'],
        'invoice_collection_id' => $invoiceCollection['id'],
    ]);
    $product = api_fixtures()->createProduct([
        'name' => 'Spot Free rinse',
        'price' => 80,
    ]);
    bulk_action_configure_rule_product('restrictSpotFree', (int)$product['id']);
    $orderItem = api_fixtures()->createOrderItem([
        'order_id' => $order['id'],
        'product_id' => $product['id'],
        'cashier_id' => 1,
        'price' => 80,
    ]);
    $session = api_fixtures()->createUserSession(['reset_collected_invoice_economic']);

    $previewResponse = api_client()->post('/collected-invoices/bulk-actions/preview', [
        'action' => 'remove_customer_rule_violations',
        'invoice_collection_ids' => [$invoiceCollection['id']],
        'locale' => 'da',
    ], $session['headers']);

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

    $preview = $previewResponse->data();
    expect($preview['preview_id'] ?? null)->toBeString()
        ->and($preview['confirmation_phrase'] ?? null)->toBe('Bekræft')
        ->and($preview['summary']['changed_count'] ?? null)->toBe(1)
        ->and($preview['order_items'][0]['order_item_id'] ?? null)->toBe((int)$orderItem['id'])
        ->and(bulk_action_order_item_deleted_at((int)$orderItem['id']))->toBeNull();

    api_client()->post('/collected-invoices/bulk-actions/apply', [
        'preview_id' => $preview['preview_id'],
        'action' => 'remove_customer_rule_violations',
        'invoice_collection_ids' => [$invoiceCollection['id']],
        'confirmation_text' => 'Bekraeft',
        'locale' => 'da',
    ], $session['headers'])
        ->assertStatus(400)
        ->assertEnvelope()
        ->assertSuccess(false);

    expect(bulk_action_order_item_deleted_at((int)$orderItem['id']))->toBeNull();

    $applyResponse = api_client()->post('/collected-invoices/bulk-actions/apply', [
        'preview_id' => $preview['preview_id'],
        'action' => 'remove_customer_rule_violations',
        'invoice_collection_ids' => [$invoiceCollection['id']],
        'confirmation_text' => 'Bekræft',
        'locale' => 'da',
    ], $session['headers']);

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

    $applied = $applyResponse->data();
    expect($applied['preview'] ?? null)->toBeFalse()
        ->and($applied['result']['changed_count'] ?? null)->toBe(1)
        ->and(bulk_action_order_item_deleted_at((int)$orderItem['id']))->not->toBeNull();
});

it('previews and applies customer rule cleanup for both spotfree addon products', function (): void {
    api_test_covers('POST /collected-invoices/bulk-actions/preview', 'customer-rule-cleanup-spotfree-addons');
    api_test_covers('POST /collected-invoices/bulk-actions/apply', 'customer-rule-cleanup-spotfree-addons');

    $customer = api_fixtures()->createUser(['display_name' => 'Bulk Cleanup Spotfree Addons Customer']);
    api_fixtures()->addCustomerAttribute((int)$customer['id'], 'restrictSpotFree');
    $department = api_fixtures()->createDepartment();
    $invoiceCollection = api_fixtures()->createInvoiceCollection([
        'customer_number' => $customer['customer_number'],
    ]);
    $order = api_fixtures()->createOrder([
        'customer_id' => $customer['customer_number'],
        'department_id' => $department['id'],
        'invoice_collection_id' => $invoiceCollection['id'],
    ]);
    $spotfreeVanProduct = api_fixtures()->createProduct([
        'id' => 23,
        'name' => 'Skylning med RO - Varevogn',
        'category' => 4,
        'price' => 39,
    ]);
    $spotfreeTruckProduct = api_fixtures()->createProduct([
        'id' => 24,
        'name' => 'Skylning med RO - Lastbil',
        'category' => 4,
        'price' => 39,
    ]);
    bulk_action_configure_rule_product('restrictSpotFree', (int)$spotfreeVanProduct['id']);
    bulk_action_configure_rule_product('restrictSpotFree', (int)$spotfreeTruckProduct['id']);
    $vanOrderItem = api_fixtures()->createOrderItem([
        'order_id' => $order['id'],
        'product_id' => $spotfreeVanProduct['id'],
        'cashier_id' => 1,
        'price' => 39,
    ]);
    $truckOrderItem = api_fixtures()->createOrderItem([
        'order_id' => $order['id'],
        'product_id' => $spotfreeTruckProduct['id'],
        'cashier_id' => 1,
        'price' => 39,
    ]);
    $session = api_fixtures()->createUserSession(['reset_collected_invoice_economic']);

    $previewResponse = api_client()->post('/collected-invoices/bulk-actions/preview', [
        'action' => 'remove_customer_rule_violations',
        'invoice_collection_ids' => [$invoiceCollection['id']],
        'locale' => 'en',
    ], $session['headers']);

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

    $preview = $previewResponse->data();
    $previewOrderItemIds = array_map('intval', array_column($preview['order_items'] ?? [], 'order_item_id'));
    sort($previewOrderItemIds);

    expect($preview['summary']['changed_count'] ?? null)->toBe(2)
        ->and($previewOrderItemIds)->toBe([(int)$vanOrderItem['id'], (int)$truckOrderItem['id']])
        ->and(bulk_action_order_item_deleted_at((int)$vanOrderItem['id']))->toBeNull()
        ->and(bulk_action_order_item_deleted_at((int)$truckOrderItem['id']))->toBeNull();

    $applyResponse = api_client()->post('/collected-invoices/bulk-actions/apply', [
        'preview_id' => $preview['preview_id'],
        'action' => 'remove_customer_rule_violations',
        'invoice_collection_ids' => [$invoiceCollection['id']],
        'confirmation_text' => 'Confirm',
        'locale' => 'en',
    ], $session['headers']);

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

    expect(bulk_action_order_item_deleted_at((int)$vanOrderItem['id']))->not->toBeNull()
        ->and(bulk_action_order_item_deleted_at((int)$truckOrderItem['id']))->not->toBeNull();
});

it('merges selected invoice collections into the explicit target after confirmation', function (): void {
    api_test_covers('POST /collected-invoices/bulk-actions/preview', 'merge');
    api_test_covers('POST /collected-invoices/bulk-actions/apply', 'merge');

    $customer = api_fixtures()->createUser(['display_name' => 'Bulk Merge Customer']);
    $department = api_fixtures()->createDepartment();
    $targetCollection = api_fixtures()->createInvoiceCollection([
        'customer_number' => $customer['customer_number'],
    ]);
    $sourceCollection = api_fixtures()->createInvoiceCollection([
        'customer_number' => $customer['customer_number'],
    ]);
    $targetOrder = api_fixtures()->createOrder([
        'customer_id' => $customer['customer_number'],
        'department_id' => $department['id'],
        'invoice_collection_id' => $targetCollection['id'],
    ]);
    $sourceOrder = api_fixtures()->createOrder([
        'customer_id' => $customer['customer_number'],
        'department_id' => $department['id'],
        'invoice_collection_id' => $sourceCollection['id'],
    ]);
    $session = api_fixtures()->createUserSession(['move_collected_invoice']);

    $previewResponse = api_client()->post('/collected-invoices/bulk-actions/preview', [
        'action' => 'merge_collections',
        'invoice_collection_ids' => [$sourceCollection['id'], $targetCollection['id']],
        'options' => ['target_invoice_collection_id' => $targetCollection['id']],
        'locale' => 'en',
    ], $session['headers']);

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

    $preview = $previewResponse->data();
    expect($preview['confirmation_phrase'] ?? null)->toBe('Confirm')
        ->and($preview['target_invoice_collection_id'] ?? null)->toBe((int)$targetCollection['id'])
        ->and($preview['summary']['orders_to_move'] ?? null)->toBe(1)
        ->and(bulk_action_order_invoice_collection_id((int)$sourceOrder['id']))->toBe((int)$sourceCollection['id']);

    $applyResponse = api_client()->post('/collected-invoices/bulk-actions/apply', [
        'preview_id' => $preview['preview_id'],
        'action' => 'merge_collections',
        'invoice_collection_ids' => [$sourceCollection['id'], $targetCollection['id']],
        'options' => ['target_invoice_collection_id' => $targetCollection['id']],
        'confirmation_text' => 'Confirm',
        'locale' => 'en',
    ], $session['headers']);

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

    expect(bulk_action_order_invoice_collection_id((int)$sourceOrder['id']))->toBe((int)$targetCollection['id'])
        ->and(bulk_action_order_invoice_collection_id((int)$targetOrder['id']))->toBe((int)$targetCollection['id']);
});
