const TdPrompt = require('@tdprompt/td-prompt.js');
const GeminiClient = require('@tdprompt/genkit-client.js');
const GenkitModels = require('@tdprompt/genkit-models.js');

// Define the API models to test and report
// .....

// TdPrompt will run and benchmark the scenarios
(new TdPrompt(apiModels)).benchmark(function (params) {

    describe(`Restaurant orders agent - evaluating ${params?.model}`, function () {
        let geminiClient, prompt, json;

        // Setup current model from the list
        before(async function () {
            // Load prompt template, we use EJS for flexible parametrization
            // .....
        });

        describe('order creation', function () {
            // .....
        });

        describe('order updates', function () {
            [
                {
                    message: 'please add a cheese cake to my order', 
                    expected: ['cheese cake', 1]
                },
                {
                    message: 'please add a sandwich with american cheese and mayo to my order', 
                    expected: ['sandwich', 1, ['american cheese', 'mayo']]
                },
                {
                    message: 'I just want 1 chocolate ice cream, with only sprinkles', 
                    expected: ['chocolate ice cream', 1, ['sprinkles']]
                },
                {
                    message: 'I want the cocacola with ice, and also 2 cheese cakes', 
                    expected: ['cocacola', 1, ['ice']]
                },
                {
                    message: 'now I want the cocacola with ice, and also 2 cheese cakes', 
                    expected: ['cheese cake', 2]
                },
            ]
            .forEach(input => {
                it(`must update: ${input.message}`, async function () {
                    const result = await geminiClient.send(input.message, this);
                    // console.log('result:', result);
                    assert.ok(result?.text);
                    
                    const response = jsonrepair(result.text);
                    assert.ok(response);

                    json = JSON.parse(response);
                    assert.ok(json?.data);
                    assert.ok(json?.resume);

                    // Validate the item was added
                    itMustContainMenuItem(json?.data?.menuItems, ...input.expected);
                });
            });
        });
    });
});

// Helper functions
function itMustContainMenuItem(menuItems, name, quantity, extras = []) {
    const menuItem = menuItems.find(item => item?.name?.toLowerCase() === name?.toLowerCase());

    // Validate order item naming and quantity
    assert.ok(menuItem, `order must contain "${name}" item`);
    assert.equal(menuItem.quantity, quantity, `it must contain quantity of ${quantity} ${name}, instead it got ${menuItem.quantity}`);
    assert.equal(menuItem.extras?.length || 0, extras.length, `it must return ${extras.length} extras, instead it got ${menuItem.extras?.length}`);
    
    // Validate order item extras
    if(extras.length > 0) {
        for (let index = 0; index < extras.length; index++) {
            const extra = extras[index];
            assert.ok(menuItem.extras[index]?.description.toLowerCase().indexOf(extra.toLowerCase()) >= 0, `it must contain ${extra} extra`);
        }
    }
}