<?php

declare(strict_types=1);

usesApiSuite();

it('removes generated customer traces during fixture cleanup', function (): void {
    $db = api_test_runtime()->db();
    api_fixture_cleanup_ensure_optional_trace_tables($db);

    $department = api_fixtures()->createDepartment(['name' => 'Fixture Cleanup Department']);
    $customer = api_fixtures()->createUser(['display_name' => 'Fixture Cleanup Customer']);
    $cashier = api_fixtures()->createUser(['display_name' => 'Fixture Cleanup Cashier']);

    $userId = (int)$customer['id'];
    $customerNumber = (int)$customer['customer_number'];
    $cashierId = (int)$cashier['id'];
    $departmentId = (int)$department['id'];

    api_fixture_cleanup_seed_customer_traces($db, $userId, $customerNumber, $cashierId, $departmentId);

    expect(api_fixture_cleanup_trace_counts($db, $userId, $customerNumber))->toMatchArray([
        'users' => 1,
        'customer_attributes' => 1,
        'tokens' => 1,
        'user_key_value_pairs' => 1,
        'price_overrides' => 1,
        'customer_default_department' => 1,
        'customer_fixed_pricing' => 1,
        'customer_fixed_pricing_versions' => 1,
        'customer_vehicle_subscription_versions' => 1,
        'customer_discount_override_versions' => 1,
        'system_search_economic_customer_index' => 1,
        'subuser_grants' => 1,
        'collected_order_invoices' => 1,
        'orders' => 1,
        'order_items' => 1,
        'economic_module_orders' => 1,
        'stripe_module_orders' => 1,
        'stripe_payment_intents' => 1,
        'customer_vehicles' => 1,
        'customer_vehicles_addons' => 1,
        'object_attachments' => 4,
    ]);

    api_test_runtime()->endTest();

    expect(api_fixture_cleanup_trace_counts($db, $userId, $customerNumber))->toMatchArray([
        'users' => 0,
        'customer_attributes' => 0,
        'tokens' => 0,
        'user_key_value_pairs' => 0,
        'price_overrides' => 0,
        'customer_default_department' => 0,
        'customer_fixed_pricing' => 0,
        'customer_fixed_pricing_versions' => 0,
        'customer_vehicle_subscription_versions' => 0,
        'customer_discount_override_versions' => 0,
        'system_search_economic_customer_index' => 0,
        'subuser_grants' => 0,
        'collected_order_invoices' => 0,
        'orders' => 0,
        'order_items' => 0,
        'economic_module_orders' => 0,
        'stripe_module_orders' => 0,
        'stripe_payment_intents' => 0,
        'customer_vehicles' => 0,
        'customer_vehicles_addons' => 0,
        'object_attachments' => 0,
    ]);
});

it('restores preserved module config rows during fixture cleanup', function (): void {
    $db = api_test_runtime()->db();
    $module = 'fixture_cleanup';
    $variable = 'preserve_module_config_' . bin2hex(random_bytes(4));
    $moduleEscaped = $db->real_escape_string($module);
    $variableEscaped = $db->real_escape_string($variable);
    $ended = false;

    try {
        $db->query(
            "INSERT INTO `module_config` (`module`, `variable`, `value`, `type`, `created_at`, `updated_at`) " .
            "VALUES ('{$moduleEscaped}', '{$variableEscaped}', '600100', 'int', '2026-04-14 12:00:00', '2026-04-14 12:00:00')"
        );

        api_fixtures()->preserveModuleConfig($module, $variable);

        $db->query(
            "UPDATE `module_config` " .
            "SET `value` = NULL, `type` = 'string', `updated_at` = '2026-04-14 12:05:00' " .
            "WHERE `module` = '{$moduleEscaped}' AND `variable` = '{$variableEscaped}'"
        );

        api_test_runtime()->endTest();
        $ended = true;

        $row = api_fixture_cleanup_module_config_row($db, $module, $variable);

        expect($row)
            ->not->toBeNull()
            ->and($row['value'] ?? null)->toBe('600100')
            ->and($row['type'] ?? null)->toBe('int')
            ->and($row['created_at'] ?? null)->toBe('2026-04-14 12:00:00')
            ->and($row['updated_at'] ?? null)->toBe('2026-04-14 12:00:00');
    } finally {
        if (!$ended) {
            api_test_runtime()->endTest();
        }

        $db->query(
            "DELETE FROM `module_config` WHERE `module` = '{$moduleEscaped}' AND `variable` = '{$variableEscaped}'"
        );
    }
});

function api_fixture_cleanup_ensure_optional_trace_tables(mysqli $db): void
{
    $statements = [
        <<<'SQL'
CREATE TABLE IF NOT EXISTS `customer_default_department` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `customer_number` INT NOT NULL,
    `department` INT NOT NULL,
    `created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
    `updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `idx_customer_default_department_customer_number` (`customer_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
        <<<'SQL'
CREATE TABLE IF NOT EXISTS `customer_fixed_pricing` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `customer_number` INT NOT NULL,
    `price` INT NOT NULL,
    `description` VARCHAR(255) NULL,
    `created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
    `updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `idx_customer_fixed_pricing_customer_number` (`customer_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
        <<<'SQL'
CREATE TABLE IF NOT EXISTS `customer_fixed_pricing_versions` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `customer_number` INT NOT NULL,
    `price` INT NOT NULL,
    `description` VARCHAR(255) NULL,
    `effective_from` DATETIME NOT NULL,
    `effective_to` DATETIME NULL,
    `source` VARCHAR(64) NOT NULL DEFAULT 'fixture.test',
    `confidence` DECIMAL(6,5) NOT NULL DEFAULT 1.00000,
    `inferred` TINYINT(1) NOT NULL DEFAULT 0,
    `metadata_json` TEXT NULL,
    `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `idx_customer_fixed_pricing_versions_customer_number` (`customer_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
        <<<'SQL'
CREATE TABLE IF NOT EXISTS `customer_vehicle_subscription_versions` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `vehicle_id` INT NULL,
    `customer_number` INT NOT NULL,
    `reg` VARCHAR(64) NOT NULL,
    `vehicle_type` INT NOT NULL,
    `wash_subscription` TINYINT(1) NOT NULL,
    `effective_from` DATETIME NOT NULL,
    `effective_to` DATETIME NULL,
    `source` VARCHAR(64) NOT NULL DEFAULT 'fixture.test',
    `confidence` DECIMAL(6,5) NOT NULL DEFAULT 1.00000,
    `inferred` TINYINT(1) NOT NULL DEFAULT 0,
    `metadata_json` TEXT NULL,
    `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `idx_customer_vehicle_subscription_versions_customer_number` (`customer_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
        <<<'SQL'
CREATE TABLE IF NOT EXISTS `customer_discount_override_versions` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `user_id` INT NOT NULL,
    `customer_number` INT NOT NULL,
    `is_category` TINYINT(1) NOT NULL,
    `object_id` VARCHAR(64) NOT NULL,
    `discount` INT NOT NULL,
    `fixed_price` INT NULL DEFAULT NULL,
    `effective_from` DATETIME NOT NULL,
    `effective_to` DATETIME NULL,
    `source` VARCHAR(64) NOT NULL DEFAULT 'fixture.test',
    `confidence` DECIMAL(6,5) NOT NULL DEFAULT 1.00000,
    `inferred` TINYINT(1) NOT NULL DEFAULT 0,
    `metadata_json` TEXT NULL,
    `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `idx_customer_discount_override_versions_customer_number` (`customer_number`),
    KEY `idx_customer_discount_override_versions_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
        <<<'SQL'
CREATE TABLE IF NOT EXISTS `system_search_economic_customer_index` (
    `customer_number` INT NOT NULL,
    `user_id` INT NULL,
    `local_display_name` VARCHAR(255) NULL,
    `local_email` VARCHAR(255) NULL,
    `local_phone` VARCHAR(64) NULL,
    `economic_name` VARCHAR(255) NULL,
    `economic_address` VARCHAR(255) NULL,
    `economic_city` VARCHAR(255) NULL,
    `economic_zip` VARCHAR(64) NULL,
    `economic_email` VARCHAR(255) NULL,
    `economic_cvr` VARCHAR(64) NULL,
    `economic_mobile_phone` VARCHAR(64) NULL,
    `economic_barred` TINYINT(1) NULL,
    `search_text` TEXT NULL,
    `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`customer_number`),
    KEY `idx_system_search_economic_customer_index_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
    ];

    foreach ($statements as $sql) {
        $db->query($sql);
    }
}

function api_fixture_cleanup_seed_customer_traces(
    mysqli $db,
    int $userId,
    int $customerNumber,
    int $cashierId,
    int $departmentId
): void {
    $now = '2026-04-14 12:00:00';
    api_fixture_cleanup_insert($db, 'customer_attributes', [
        'user_id' => $userId,
        'attribute' => 'fixture_cleanup_attribute',
        'created_at' => $now,
    ]);
    api_fixture_cleanup_insert($db, 'tokens', [
        'user_id' => $userId,
        'type' => 'AUTH_TOKEN',
        'description' => 'Fixture cleanup token',
        'token' => 'fixture-cleanup-' . $userId,
        'created_at' => $now,
    ]);
    api_fixture_cleanup_insert($db, 'user_key_value_pairs', [
        'user_id' => $userId,
        'var' => 'fixture_cleanup_key',
        'val' => 'fixture_cleanup_value',
        'created_at' => $now,
        'updated_at' => $now,
    ]);
    api_fixture_cleanup_insert($db, 'price_overrides', [
        'user_id' => $userId,
        'is_category' => 1,
        'product_or_category_id' => 'fixture_cleanup_category',
        'percentage' => 25,
        'created_at' => $now,
        'updated_at' => $now,
    ]);
    api_fixture_cleanup_insert($db, 'customer_default_department', [
        'customer_number' => $customerNumber,
        'department' => $departmentId,
        'created_at' => $now,
        'updated_at' => $now,
    ]);
    api_fixture_cleanup_insert($db, 'customer_fixed_pricing', [
        'customer_number' => $customerNumber,
        'price' => 1999,
        'description' => 'Fixture cleanup fixed pricing',
        'created_at' => $now,
        'updated_at' => $now,
    ]);
    api_fixture_cleanup_insert($db, 'customer_fixed_pricing_versions', [
        'customer_number' => $customerNumber,
        'price' => 1999,
        'description' => 'Fixture cleanup fixed pricing',
        'effective_from' => $now,
        'source' => 'fixture.test',
        'confidence' => 1.00000,
        'inferred' => 0,
        'metadata_json' => '{}',
    ]);
    api_fixture_cleanup_insert($db, 'customer_discount_override_versions', [
        'user_id' => $userId,
        'customer_number' => $customerNumber,
        'is_category' => 1,
        'object_id' => 'fixture_cleanup_category',
        'discount' => 25,
        'effective_from' => $now,
        'source' => 'fixture.test',
        'confidence' => 1.00000,
        'inferred' => 0,
        'metadata_json' => '{}',
    ]);
    api_fixture_cleanup_insert($db, 'system_search_economic_customer_index', [
        'customer_number' => $customerNumber,
        'user_id' => $userId,
        'local_display_name' => 'Fixture Cleanup Customer',
        'local_email' => 'fixture-cleanup@example.test',
        'search_text' => 'fixture cleanup customer',
    ]);
    api_fixture_cleanup_insert($db, 'subuser_grants', [
        'billing_customer_number' => $customerNumber,
        'subuser' => $cashierId,
        'enabled' => 1,
        'note' => 'Fixture cleanup grant',
        'permissions' => '[]',
        'created_at' => $now,
        'updated_at' => $now,
        'deleted_at' => null,
    ]);

    $invoiceCollectionId = api_fixture_cleanup_insert($db, 'collected_order_invoices', [
        'customer_number' => $customerNumber,
        'name' => 'Fixture cleanup invoice',
        'notes' => 'Fixture cleanup notes',
        'processor' => 0,
        'created_at' => $now,
        'updated_at' => $now,
    ]);

    $orderId = api_fixture_cleanup_insert($db, 'orders', [
        'customer_id' => $customerNumber,
        'cashier_id' => $cashierId,
        'department_id' => $departmentId,
        'reference' => 'FIXTURE-CLEANUP',
        'notes' => 'Fixture cleanup order',
        'reg_1' => 'FC12345',
        'invoice_collection_id' => $invoiceCollectionId,
        'using_hand_held' => 0,
        'include_in_invoice' => 1,
        'created_at' => $now,
        'updated_at' => $now,
        'completed_at' => $now,
        'deleted_at' => null,
    ]);

    api_fixture_cleanup_insert($db, 'order_items', [
        'order_id' => $orderId,
        'product_id' => 61,
        'reference' => 'FIXTURE-CLEANUP-ITEM',
        'notes' => 'Fixture cleanup item',
        'cashier_id' => $cashierId,
        'price' => 250,
        'quantity' => 1,
        'include_in_invoice' => 1,
        'created_at' => $now,
        'updated_at' => $now,
        'deleted_at' => null,
    ]);
    api_fixture_cleanup_insert($db, 'economic_module_orders', [
        'id' => $orderId,
        'invoice_draft_id' => 9001,
        'invoice_id' => 9002,
        'created_at' => $now,
        'updated_at' => $now,
    ]);
    api_fixture_cleanup_insert($db, 'stripe_module_orders', [
        'id' => $orderId,
        'invoice_id' => 'in_fixture_cleanup',
        'customer_id' => 'cus_fixture_cleanup',
        'created_at' => $now,
        'updated_at' => $now,
    ]);
    api_fixture_cleanup_insert($db, 'stripe_payment_intents', [
        'order_id' => $orderId,
        'payment_intent_id' => 'pi_fixture_cleanup',
        'client_secret' => 'secret_fixture_cleanup',
        'data' => '{}',
        'created_at' => $now,
        'updated_at' => $now,
    ]);

    $vehicleId = api_fixture_cleanup_insert($db, 'customer_vehicles', [
        'customer_id' => $customerNumber,
        'type' => 61,
        'reg' => 'FC12345',
        'wash_subscription' => 1,
        'notes' => 'Fixture cleanup vehicle',
        'reference' => 'Fixture cleanup reference',
        'created_at' => $now,
        'updated_at' => $now,
        'deleted_at' => null,
    ]);

    api_fixture_cleanup_insert($db, 'customer_vehicles_addons', [
        'vehicle_id' => $vehicleId,
        'addon_id' => 71,
        'amount' => 1,
        'created_at' => $now,
        'updated_at' => $now,
    ]);
    api_fixture_cleanup_insert($db, 'customer_vehicle_subscription_versions', [
        'vehicle_id' => $vehicleId,
        'customer_number' => $customerNumber,
        'reg' => 'FC12345',
        'vehicle_type' => 61,
        'wash_subscription' => 1,
        'effective_from' => $now,
        'source' => 'fixture.test',
        'confidence' => 1.00000,
        'inferred' => 0,
        'metadata_json' => '{}',
    ]);

    $attachmentPayload = '{"fixture_cleanup":true}';
    api_fixture_cleanup_insert($db, 'object_attachments', [
        'object_type' => 'users',
        'object_id' => $userId,
        'content' => $attachmentPayload,
        'created_at' => $now,
        'updated_at' => $now,
        'deleted_at' => null,
    ]);
    api_fixture_cleanup_insert($db, 'object_attachments', [
        'object_type' => 'orders',
        'object_id' => $orderId,
        'content' => $attachmentPayload,
        'created_at' => $now,
        'updated_at' => $now,
        'deleted_at' => null,
    ]);
    api_fixture_cleanup_insert($db, 'object_attachments', [
        'object_type' => 'customer_vehicles',
        'object_id' => $vehicleId,
        'content' => $attachmentPayload,
        'created_at' => $now,
        'updated_at' => $now,
        'deleted_at' => null,
    ]);
    api_fixture_cleanup_insert($db, 'object_attachments', [
        'object_type' => 'collected_order_invoices',
        'object_id' => $invoiceCollectionId,
        'content' => $attachmentPayload,
        'created_at' => $now,
        'updated_at' => $now,
        'deleted_at' => null,
    ]);
}

/**
 * @return array<string, int>
 */
function api_fixture_cleanup_trace_counts(mysqli $db, int $userId, int $customerNumber): array
{
    return [
        'users' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `users` WHERE `id` = {$userId}"),
        'customer_attributes' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_attributes` WHERE `user_id` = {$userId}"),
        'tokens' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `tokens` WHERE `user_id` = {$userId}"),
        'user_key_value_pairs' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `user_key_value_pairs` WHERE `user_id` = {$userId}"),
        'price_overrides' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `price_overrides` WHERE `user_id` = {$userId}"),
        'customer_default_department' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_default_department` WHERE `customer_number` = {$customerNumber}"),
        'customer_fixed_pricing' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_fixed_pricing` WHERE `customer_number` = {$customerNumber}"),
        'customer_fixed_pricing_versions' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_fixed_pricing_versions` WHERE `customer_number` = {$customerNumber}"),
        'customer_vehicle_subscription_versions' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_vehicle_subscription_versions` WHERE `customer_number` = {$customerNumber}"),
        'customer_discount_override_versions' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_discount_override_versions` WHERE `customer_number` = {$customerNumber}"),
        'system_search_economic_customer_index' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `system_search_economic_customer_index` WHERE `customer_number` = {$customerNumber}"),
        'subuser_grants' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `subuser_grants` WHERE `billing_customer_number` = {$customerNumber}"),
        'collected_order_invoices' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `collected_order_invoices` WHERE `customer_number` = {$customerNumber}"),
        'orders' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `orders` WHERE `customer_id` = {$customerNumber}"),
        'order_items' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `order_items` WHERE `order_id` IN (SELECT `id` FROM `orders` WHERE `customer_id` = {$customerNumber})"),
        'economic_module_orders' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `economic_module_orders` WHERE `id` IN (SELECT `id` FROM `orders` WHERE `customer_id` = {$customerNumber})"),
        'stripe_module_orders' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `stripe_module_orders` WHERE `id` IN (SELECT `id` FROM `orders` WHERE `customer_id` = {$customerNumber})"),
        'stripe_payment_intents' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `stripe_payment_intents` WHERE `order_id` IN (SELECT `id` FROM `orders` WHERE `customer_id` = {$customerNumber})"),
        'customer_vehicles' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_vehicles` WHERE `customer_id` = {$customerNumber}"),
        'customer_vehicles_addons' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_vehicles_addons` WHERE `vehicle_id` IN (SELECT `id` FROM `customer_vehicles` WHERE `customer_id` = {$customerNumber})"),
        'object_attachments' => api_fixture_cleanup_count(
            $db,
            "SELECT COUNT(*) AS c
             FROM `object_attachments`
             WHERE (`object_type` = 'users' AND `object_id` = {$userId})
                OR (`object_type` = 'orders' AND `object_id` IN (SELECT `id` FROM `orders` WHERE `customer_id` = {$customerNumber}))
                OR (`object_type` = 'customer_vehicles' AND `object_id` IN (SELECT `id` FROM `customer_vehicles` WHERE `customer_id` = {$customerNumber}))
                OR (`object_type` = 'collected_order_invoices' AND `object_id` IN (SELECT `id` FROM `collected_order_invoices` WHERE `customer_number` = {$customerNumber}))"
        ),
    ];
}

function api_fixture_cleanup_count(mysqli $db, string $sql): int
{
    $result = $db->query($sql);
    if ($result === false) {
        throw new RuntimeException('Fixture cleanup assertion query failed: ' . $sql);
    }

    $row = $result->fetch_assoc();
    $result->free();

    return (int)($row['c'] ?? 0);
}

function api_fixture_cleanup_module_config_row(mysqli $db, string $module, string $variable): ?array
{
    $moduleEscaped = $db->real_escape_string($module);
    $variableEscaped = $db->real_escape_string($variable);
    $result = $db->query(
        "SELECT * FROM `module_config` WHERE `module` = '{$moduleEscaped}' AND `variable` = '{$variableEscaped}' LIMIT 1"
    );

    if ($result === false) {
        throw new RuntimeException('Fixture cleanup module_config query failed.');
    }

    $row = $result->fetch_assoc();
    $result->free();

    return $row ?: null;
}

/**
 * @param array<string, mixed> $data
 */
function api_fixture_cleanup_insert(mysqli $db, string $table, array $data): int
{
    $filtered = [];
    foreach ($data as $column => $value) {
        if (api_fixture_cleanup_has_column($db, $table, $column)) {
            $filtered[$column] = $value;
        }
    }

    if ($filtered === []) {
        throw new RuntimeException('No matching columns available for fixture cleanup insert into ' . $table . '.');
    }

    $columns = array_map(
        static fn(string $column): string => '`' . $column . '`',
        array_keys($filtered)
    );
    $values = array_map(
        static fn(mixed $value): string => api_fixture_cleanup_sql_value($db, $value),
        array_values($filtered)
    );

    $sql = 'INSERT INTO `' . $table . '` (' . implode(', ', $columns) . ') VALUES (' . implode(', ', $values) . ')';
    if ($db->query($sql) === false) {
        throw new RuntimeException('Fixture cleanup insert failed: ' . $sql);
    }

    return (int)$db->insert_id;
}

function api_fixture_cleanup_has_column(mysqli $db, string $table, string $column): bool
{
    static $cache = [];

    $cacheKey = $table . ':' . $column;
    if (array_key_exists($cacheKey, $cache)) {
        return $cache[$cacheKey];
    }

    $escapedTable = $db->real_escape_string($table);
    $escapedColumn = $db->real_escape_string($column);
    $result = $db->query(
        "SELECT 1
         FROM information_schema.COLUMNS
         WHERE TABLE_SCHEMA = DATABASE()
           AND TABLE_NAME = '{$escapedTable}'
           AND COLUMN_NAME = '{$escapedColumn}'
         LIMIT 1"
    );
    if ($result === false) {
        return $cache[$cacheKey] = false;
    }

    $exists = $result->fetch_assoc() !== null;
    $result->free();

    return $cache[$cacheKey] = $exists;
}

function api_fixture_cleanup_sql_value(mysqli $db, mixed $value): string
{
    if ($value === null) {
        return 'NULL';
    }

    if (is_bool($value)) {
        return $value ? '1' : '0';
    }

    if (is_int($value) || is_float($value)) {
        return (string)$value;
    }

    return "'" . $db->real_escape_string((string)$value) . "'";
}
