<?php

usesApiSuite();

function selfserve_fixture_ensure_legacy_redis_constant(): void
{
    if (defined('redis')) {
        return;
    }

    global $REDIS_CONFIG;

    $REDIS_CONFIG = [
        'host' => getenv('REDIS_CONFIG_HOST') ?: getenv('REDIS_CONFIG_DEBUG_HOST') ?: 'redis',
        'user' => getenv('REDIS_CONFIG_USER') ?: getenv('REDIS_CONFIG_DEBUG_USER') ?: 'default',
        'database' => getenv('REDIS_CONFIG_DATABASE') ?: getenv('REDIS_CONFIG_DEBUG_DATABASE') ?: '0',
        'password' => getenv('REDIS_CONFIG_PASSWORD') ?: getenv('REDIS_CONFIG_DEBUG_PASSWORD') ?: '',
        'port' => getenv('REDIS_CONFIG_PORT') ?: getenv('REDIS_CONFIG_DEBUG_PORT') ?: '6379',
    ];

    define('redis', (new \classes\redis())->connect());
}

it('creates a comprehensive self-serve API scenario with demo relays', function (): void {
    $scenario = api_fixtures()->createSelfServeScenario();

    expect($scenario['relay_ids']['machine'])->toStartWith('demo-')
        ->and($scenario['relay_ids']['entry'])->toStartWith('demo-')
        ->and($scenario['lane']['relay_machine_id'])->toStartWith('demo-')
        ->and($scenario['session']['status'])->toBe('MACHINE_STARTED')
        ->and($scenario['session']['metadata_json']['relay_ids']['machine'])->toBe($scenario['relay_ids']['machine'])
        ->and($scenario['tasks'])->toHaveCount(2)
        ->and($scenario['events'])->toHaveCount(3);

    $lane = api_fixtures()->fetchRowById('department_lanes', (int)$scenario['lane']['id']);
    $session = api_fixtures()->fetchRowById('selfserve_wash_sessions', (int)$scenario['session']['id']);

    expect($lane)->not->toBeNull()
        ->and($lane['relay_machine_id'])->toBe($scenario['relay_ids']['machine'])
        ->and($session)->not->toBeNull()
        ->and($session['reg'])->toBe($scenario['vehicle']['reg']);
});

it('creates self-serve invoice orders for the lane customer with draft customer and driver metadata attached', function (): void {
    selfserve_fixture_ensure_legacy_redis_constant();

    $draftCustomer = api_fixtures()->createUser(['display_name' => 'Self-Serve Draft Customer']);
    $scenario = api_fixtures()->createSelfServeScenario();
    $subuser = api_fixtures()->createSubuser([
        'name' => 'Self-Serve Driver',
        'username' => 'selfserve-driver-' . $scenario['vehicle']['reg'],
    ]);

    api_fixtures()->setModuleConfig('economic', 'transactionDraftCustomerNumber', (string)$draftCustomer['customer_number'], 'int');
    api_fixtures()->setModuleConfig('selfserve', 'minute_product', (string)$scenario['product']['id'], 'int');

    $lane = (new \classes\selfserve())->lane((int)$scenario['lane']['id']);
    $lane->setLaneStatus(\modules\selfserve\helpers\selfserve_lane_status::OCCUPIED);
    $lane->setLaneState(\modules\selfserve\helpers\selfserve_lane_state::IN_WASH);
    $lane->setLaneMode(\modules\selfserve\helpers\selfserve_lane_mode::MANUAL);
    $lane->setCustomerNumber((int)$scenario['customer']['customer_number']);
    $lane->setLicensePlate((string)$scenario['vehicle']['reg']);
    $lane->setWashStartTime(time() - 620);

    $arguments = (new \modules\selfserve\classes\selfserve_lane_command_arguments())
        ->setCustomerNumber((int)$scenario['customer']['customer_number'])
        ->setSubuserId((int)$subuser['id']);

    expect($lane->invoice($arguments))->toBeTrue();

    $orderId = $lane->getLastInvoiceOrderId();
    expect($orderId)->toBeInt()->toBeGreaterThan(0);

    $order = api_fixtures()->fetchRowById('orders', $orderId);
    $attachmentObjectType = '`orders`';
    $invoiceCollectionId = (int)($order['invoice_collection_id'] ?? 0);
    if ($invoiceCollectionId > 0) {
        api_fixtures()->cleanupDeleteById('collected_order_invoices', $invoiceCollectionId);
    }
    api_fixtures()->cleanupDeleteById('orders', $orderId);
    api_fixtures()->cleanupDeleteWhere('order_items', ['order_id' => $orderId]);
    api_fixtures()->cleanupDeleteWhere('object_attachments', ['object_type' => $attachmentObjectType, 'object_id' => $orderId]);

    expect($order)->not->toBeNull()
        ->and((int)$order['customer_id'])->toBe((int)$scenario['customer']['customer_number'])
        ->and((int)$order['department_id'])->toBe((int)$scenario['department']['id'])
        ->and((string)$order['reg_1'])->toBe((string)$scenario['vehicle']['reg'])
        ->and((int)$order['lane'])->toBe((int)$scenario['lane']['id'])
        ->and($order['completed_at'])->toBeNull();

    $db = api_test_runtime()->db();
    $result = $db->query(
        "SELECT content FROM object_attachments WHERE object_type = '{$attachmentObjectType}' AND object_id = " . (int)$orderId . ' AND deleted_at IS NULL ORDER BY id DESC LIMIT 1'
    );
    $attachment = $result ? $result->fetch_assoc() : null;
    $content = json_decode((string)($attachment['content'] ?? ''), true);
    $metadata = is_array($content) ? ($content['other'] ?? null) : null;

    expect($metadata)->toBeArray()
        ->and($metadata['type'] ?? null)->toBe(\attachments\helpers\attachment_content::OTHER_TYPE_SELF_SERVE_WASH)
        ->and((int)($metadata['customer_number'] ?? 0))->toBe((int)$scenario['customer']['customer_number'])
        ->and((int)($metadata['draft_customer_number'] ?? 0))->toBe((int)$draftCustomer['customer_number'])
        ->and((int)($metadata['subuser_id'] ?? 0))->toBe((int)$subuser['id'])
        ->and((int)($metadata['session_id'] ?? 0))->toBe((int)$scenario['session']['id'])
        ->and($metadata['subuser']['name'] ?? null)->toBe('Self-Serve Driver');
});
