import { test, expect, type BrowserContext, type Page, type Locator } from '@playwright/test';
import { RegistrationPage } from '../../pages/RegistrationPage';
import { waitForActivationCode } from '../../utils/ActivationCodeUtils';
import { ChatPage } from '../../pages/ChatPage';

let context: BrowserContext;
let page: Page;
let registrationPage: RegistrationPage;
let chatPage: ChatPage;
let email: string;
let password: string;

const SEARCH_LIMIT_MESSAGE = /limit|10 searches|cannot perform more than 10 searches|searches exceeded|quota|maximum searches|failed/i;
const B3_CHAT_PROMPTS = {
    domain: 'I need to create a domain',
    agent: 'I need to create new agent without a domain',
    widget: 'I need to create a widget without a domain',
    curatedData: 'I need to create a dataset without a domain',
    utility: 'I need to create a utility without a domain',
    chain: 'I need to create a chain of agents without a domain',
    media: 'I need to create media without a domain',
    model: 'I need to create a model without a domain',
    marketplace: 'I need a case management system',
    marketplaceKf: 'I need a contract management system',
    marketplaceMkf: 'I need a matter finance agent',
    marketplaceWidgetCase: 'I need a case intake widget',
    marketplaceWidgetMatter: 'I need a matter finance widget',
    marketplaceWidgetFraud: 'I need a fraud prevention playbook widget',
    marketplaceChainDecision: 'I need a decision analyzer chain',
    marketplaceChainCdr: 'I need a CDR analysis chain',
    marketplaceChainSales: 'I need a full cycle sales accelerator chain',
    marketplaceUtilityCase: 'I need a case management utility',
    marketplaceUtilityInsight: 'I need an insight table manager utility',
    marketplaceUtilityFeedback: 'I need a feedback analysis utility',
    marketplaceCuratedCustomer: 'I need a customer data set',
    marketplaceMediaCaseDocs: 'I need case documents media',
    marketplaceModelHospital: 'I need a hospital resource utilization model',
    search: 'Find automation testing solutions for QA workflows',
    alerts: 'How can I set up Slack alerts for automation failures?'
};


async function isVisible(locator: ReturnType<Page['locator']> | any, timeout = 1500): Promise<boolean> {
    return locator.isVisible({ timeout }).catch(() => false);
}

async function closeWelcomePopupOnly(page: Page, appearanceTimeout = 10000) {
    const welcomePopup = page.getByText(/Welcome to RoboCorp!/i).first();
    const welcomeModal = page.locator(
        "xpath=//div[.//*[contains(normalize-space(.), 'Welcome to RoboCorp!')] and .//input[@type='checkbox']]"
    ).first();
    const primaryCloseButton = page.locator('#welcome-cards-banner button.absolute').first();
    const fallbackCloseButton = welcomeModal.locator('button.absolute').first();

    const deadline = Date.now() + appearanceTimeout;
    while (Date.now() < deadline) {
        if (await isVisible(welcomePopup, 1000)) break;
        await page.waitForTimeout(250);
    }

    if (!(await isVisible(welcomePopup, 1000))) return;

    for (const closeButton of [primaryCloseButton, fallbackCloseButton]) {
        if (!(await isVisible(closeButton, 1500))) continue;

        await closeButton.click({ force: true }).catch(() => {});
        let closed = await welcomePopup.waitFor({ state: 'hidden', timeout: 3000 }).then(() => true).catch(() => false);
        if (!closed) {
            await closeButton.click({ force: true }).catch(() => {});
            closed = await welcomePopup.waitFor({ state: 'hidden', timeout: 3000 }).then(() => true).catch(() => false);
        }
        if (closed) return;
    }

    await page.keyboard.press('Escape').catch(() => {});
    await expect(welcomePopup).toBeHidden({ timeout: 3000 });
}

async function ensureMarketplaceExpanded(page: Page, marketplaceHeading: Locator) {
    const expandButton = page
        .getByRole('button', { name: /Expand widget|Maximize widget|Open widget/i })
        .first();

    if (await expandButton.isVisible({ timeout: 2000 }).catch(() => false)) {
        await expandButton.click();
    }

    await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });
}

async function advanceTipsToChat(page: Page) {
    const continueButton = page.getByRole('button', { name: /^Continue$/i }).first();
    const tipsText = page.getByText(/Here is tips how to use our platform|Traditional search engines return links/i).first();
    const chatInput = page.getByPlaceholder('Ask anything...').first();
    const welcomeBanner = page.locator('#welcome-cards-banner');

    for (let i = 0; i < 6; i++) {
        const chatReady = await chatInput.isVisible({ timeout: 1000 }).catch(() => false);
        const tipsVisible = await tipsText.isVisible({ timeout: 1000 }).catch(() => false);
        if (chatReady && !tipsVisible) {
            return;
        }

        if (!(await continueButton.isVisible({ timeout: 1000 }).catch(() => false))) {
            break;
        }

        await continueButton.click();
        await Promise.race([
            welcomeBanner.waitFor({ state: 'visible', timeout: 3000 }).catch(() => null),
            page.waitForTimeout(800)
        ]);
    }
}

async function sendSearchAndWaitForResponse(query: string) {
    const previousCount = await chatPage.getReceivedMessageCount();
    await chatPage.sendMessage(query);
    await chatPage.waitForNewReceivedMessage(previousCount);
    return chatPage.getLastReceivedMessage();
}

async function expectPromptDoesNotHitLimit(prompt: string) {
    const response = await sendSearchAndWaitForResponse(prompt);
    expect(response).not.toMatch(SEARCH_LIMIT_MESSAGE);
}

async function expectPromptHitsLimit(prompt: string) {
    const response = await sendSearchAndWaitForResponse(prompt);
    expect(response).toMatch(SEARCH_LIMIT_MESSAGE);
}

async function openAssetPurchase(assetName: string, page: Page) {
    const escaped = assetName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    const fullRegex = new RegExp(escaped, 'i');
    const partialText = assetName.split(/\s+/).slice(0, 3).join(' ').trim();
    const partialRegex = partialText
        ? new RegExp(partialText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i')
        : fullRegex;

    const findCardAndDetailsButton = (nameRegex: RegExp) => {
        const heading = page.getByRole('heading', { name: nameRegex }).first();
        const card = heading
            .locator('xpath=ancestor::*[self::button or self::div][.//button[contains(., "See details")]]')
            .first();
        const detailsButton = card.getByRole('button', { name: /See details/i }).first();
        return { heading, card, detailsButton };
    };

    let { heading, card, detailsButton } = findCardAndDetailsButton(fullRegex);
    if (!(await detailsButton.isVisible({ timeout: 3000 }).catch(() => false))) {
        ({ heading, card, detailsButton } = findCardAndDetailsButton(partialRegex));
    }

    await expect(heading).toBeVisible({ timeout: 20000 });
    await heading.scrollIntoViewIfNeeded();

    if (await card.isVisible({ timeout: 3000 }).catch(() => false)) {
        await card.hover().catch(() => {});
    }

    await expect(detailsButton).toBeVisible({ timeout: 5000 });
    await detailsButton.click();

    const popupById = page.locator('#product-view-popup');
    try {
        await expect(popupById).toBeVisible({ timeout: 15000 });
    } catch {
        const cardExpandButton = card
            .locator('[id^="btn_expand_domain_driven_agent_"], [id^="btn_expand_"]')
            .first();
        if (await detailsButton.isVisible({ timeout: 2000 }).catch(() => false)) {
            await detailsButton.click({ force: true });
        } else if (await cardExpandButton.isVisible({ timeout: 2000 }).catch(() => false)) {
            await cardExpandButton.click({ force: true });
        } else if (await card.isVisible({ timeout: 2000 }).catch(() => false)) {
            await card.click({ force: true });
        } else {
            throw new Error(`Unable to reopen details for asset: ${assetName}`);
        }
        await expect(popupById).toBeVisible({ timeout: 15000 });
    }

    const purchaseButton = popupById.getByRole('button', { name: /^Purchase$/i }).first();
    await expect(purchaseButton).toBeVisible({ timeout: 15000 });
    await purchaseButton.scrollIntoViewIfNeeded();
    await purchaseButton.click();
}

async function openLegalCaseDetailsById(page: Page) {
    const detailsButton = page.locator('#btn_expand_domain_driven_agent_0');
    await expect(detailsButton).toBeVisible({ timeout: 10000 });
    await detailsButton.click();
    const popupById = page.locator('#product-view-popup');
    await expect(popupById).toBeVisible({ timeout: 15000 });
}

async function openFirstDomainDrivenAgentDetails(page: Page) {
    const detailsButton = page.locator('[id^="btn_expand_domain_driven_agent_"]').first();
    await expect(detailsButton).toBeVisible({ timeout: 10000 });
    await detailsButton.click();
    const popupById = page.locator('#product-view-popup');
    await expect(popupById).toBeVisible({ timeout: 15000 });
}

async function expectPurchaseError(page: Page) {
    const errorRegex = /error.*purchas|active DAAC wallet/i;
    const errorToast = page.getByRole('alert').filter({ hasText: errorRegex }).first();
    const errorText = page.getByText(errorRegex).first();

    await expect(async () => {
        if (await errorToast.isVisible({ timeout: 500 }).catch(() => false)) return;
        if (await errorText.isVisible({ timeout: 500 }).catch(() => false)) return;
        throw new Error('Purchase error message not visible yet.');
    }).toPass({ timeout: 20000 });
}

async function waitForPurchaseErrorToHide(page: Page) {
    const errorRegex = /error.*purchas|active DAAC wallet/i;
    const errorToast = page.getByRole('alert').filter({ hasText: errorRegex }).first();
    const errorText = page.getByText(errorRegex).first();

    await expect(async () => {
        const toastVisible = await errorToast.isVisible({ timeout: 500 }).catch(() => false);
        const textVisible = await errorText.isVisible({ timeout: 500 }).catch(() => false);
        if (!toastVisible && !textVisible) return;
        throw new Error('Purchase error message still visible.');
    }).toPass({ timeout: 20000 });
}

async function closeProductViewPopup(page: Page) {
    const popup = page.locator('#product-view-popup');
    if (!(await popup.isVisible({ timeout: 2000 }).catch(() => false))) {
        return;
    }

    const popupBox = await popup.boundingBox();
    if (popupBox) {
        await page.mouse.click(popupBox.x + 12, popupBox.y + 12);
        await page.waitForTimeout(300);
    }

    const closeByRole = page.getByRole('button', { name: 'close' }).first();
    await expect(closeByRole).toBeVisible({ timeout: 5000 });
    for (let attempt = 0; attempt < 5; attempt++) {
        await closeByRole.click({ force: true, timeout: 5000 }).catch(() => {});
        await page.waitForTimeout(2000);
        if (await popup.isHidden({ timeout: 1000 }).catch(() => false)) return;
    }

    const closeCandidates = [
        popup.getByRole('button', { name: /close|dismiss|x/i }).first(),
        popup.locator('button[aria-label*="Close" i]').first(),
        popup.locator('button[title*="Close" i]').first()
    ];

    for (const candidate of closeCandidates) {
        if (await candidate.isVisible({ timeout: 1500 }).catch(() => false)) {
            await candidate.click({ force: true, timeout: 5000 }).catch(() => {});
            if (await popup.isHidden({ timeout: 3000 }).catch(() => false)) {
                return;
            }
        }
    }

    await page.keyboard.press('Escape').catch(() => {});
    await expect(popup).toBeHidden({ timeout: 5000 });
}


test.describe.serial('Business Users / B3 User', () => {
    test.describe.configure({ timeout: 180000 });

    test.beforeAll(async ({ browser }) => {
        context = await browser.newContext();
        page = await context.newPage();
        registrationPage = new RegistrationPage(page);
        chatPage = new ChatPage(page);

        email = `automation.b3+${Date.now()}@datafab.ai`;
        password = process.env.USER_PASSWORD?.trim() || 'Password123!';

        await registrationPage.gotoSignIn();
        await registrationPage.openSignUpFromSignIn();
        await registrationPage.submitSignUpCredentials(email, password);
        await registrationPage.submitFullName('Automation B Three User');

        await registrationPage.waitForVerificationScreen();
        const code = await waitForActivationCode(email, { timeoutMs: 90000, intervalMs: 3000 });
        await registrationPage.enterVerificationCode(code);
        await registrationPage.clickVerify();
    });

    test.afterAll(async () => {
        await context?.close();
    });

    test('should register and activate successfully', async () => {
        await expect(page).toHaveURL(/\/sign-in\/account/i, { timeout: 30000 });
        await expect(page.locator('body')).not.toContainText(/please check your email/i, { timeout: 10000 });
    });

    test('should keep the user on the account selection milestone', async () => {
        await expect(page).toHaveURL(/\/sign-in\/account/i, { timeout: 10000 });
        await expect(page.locator('body')).toContainText(/What best describes you\?/i, { timeout: 30000 });
    });

    test('should show both account type options', async () => {
        await expect(registrationPage.individualUserOption).toBeVisible({ timeout: 30000 });
        await expect(registrationPage.businessUserOption).toBeVisible({ timeout: 30000 });
    });

    test('should complete business user type selection after activation', async () => {
        await registrationPage.completeBusinessUserConsumerFlow();
        await registrationPage.waitForTipsOrOnboarding();
        await expect(page.locator('body')).toContainText(/Here is tips how to use our platform|Traditional search engines return links/i, {
            timeout: 30000
        });
    });

    test('should close pop up boxes and leave the user on the chat ui', async () => {
        await advanceTipsToChat(page);
        await closeWelcomePopupOnly(page);

        const skipForNow = page.getByRole('button', { name: /Skip for now/i }).first();
        if (await skipForNow.isVisible({ timeout: 3000 }).catch(() => false)) {
            await skipForNow.click();
        }

        await expect(page.getByPlaceholder('Ask anything...')).toBeVisible({ timeout: 30000 });
        await expect(page.locator('body')).not.toContainText(/What best describes you\?|Verify your business profile/i, { timeout: 5000 });
    });

    test('should show DDA without sources marketplace asset', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplace);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const domainDrivenFilter = page.getByRole('button', { name: /Domain Driven Agent/i }).first();
        await expect(domainDrivenFilter).toBeVisible({ timeout: 10000 });
        await domainDrivenFilter.click();

        const targetAsset = page.getByText(/Legal Case Intake & Classification Agent/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent DDA without sources marketplace purchase', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const domainDrivenFilter = page.getByRole('button', { name: /Domain Driven Agent/i }).first();
        await expect(domainDrivenFilter).toBeVisible({ timeout: 10000 });
        await domainDrivenFilter.click();

        const targetAsset = page.getByText(/Legal Case Intake & Classification Agent/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });

        await openLegalCaseDetailsById(page);

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show DDA with sources marketplace asset', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceKf);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const domainDrivenFilter = page.getByRole('button', { name: /Domain Driven Agent/i }).first();
        await expect(domainDrivenFilter).toBeVisible({ timeout: 10000 });
        await domainDrivenFilter.click();

        const targetAsset = page.getByText(/Contract Management Expert/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent DDA with sources marketplace purchase', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const domainDrivenFilter = page.getByRole('button', { name: /Domain Driven Agent/i }).first();
        await expect(domainDrivenFilter).toBeVisible({ timeout: 10000 });
        await domainDrivenFilter.click();

        const targetAsset = page.getByText(/Contract Management Expert/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });

        await openAssetPurchase('Contract Management Expert', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show MKF with sources marketplace asset', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceMkf);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const domainDrivenFilter = page.getByRole('button', { name: /Domain Driven Agent/i }).first();
        await expect(domainDrivenFilter).toBeVisible({ timeout: 10000 });
        await domainDrivenFilter.click();

        const targetAsset = page.getByText(/Matter Finance Agent/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent MKF with sources marketplace purchase', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const domainDrivenFilter = page.getByRole('button', { name: /Domain Driven Agent/i }).first();
        await expect(domainDrivenFilter).toBeVisible({ timeout: 10000 });
        await domainDrivenFilter.click();

        const targetAsset = page.getByText(/Matter Finance Agent/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });

        await openAssetPurchase('Matter Finance Agent', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show widget marketplace asset: Case Intake Table Widget', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceWidgetCase);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const agenticWidgetFilter = page.getByRole('button', { name: /Agentic Widget/i }).first();
        await expect(agenticWidgetFilter).toBeVisible({ timeout: 10000 });
        await agenticWidgetFilter.click();

        const targetAsset = page.getByText(/Case Intake Table Widget/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent widget marketplace purchase: Case Intake Table Widget', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const agenticWidgetFilter = page.getByRole('button', { name: /Agentic Widget/i }).first();
        await expect(agenticWidgetFilter).toBeVisible({ timeout: 10000 });
        await agenticWidgetFilter.click();

        await openAssetPurchase('Case Intake Table Widget', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show widget marketplace asset: Matter Finance Information widget', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceWidgetMatter);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const agenticWidgetFilter = page.getByRole('button', { name: /Agentic Widget/i }).first();
        await expect(agenticWidgetFilter).toBeVisible({ timeout: 10000 });
        await agenticWidgetFilter.click();

        const targetAsset = page.getByText(/Matter Finance Information widget/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent widget marketplace purchase: Matter Finance Information widget', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const agenticWidgetFilter = page.getByRole('button', { name: /Agentic Widget/i }).first();
        await expect(agenticWidgetFilter).toBeVisible({ timeout: 10000 });
        await agenticWidgetFilter.click();

        await openAssetPurchase('Matter Finance Information widget', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show widget marketplace asset: CDR based fraud prevention playbook', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceWidgetFraud);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const agenticWidgetFilter = page.getByRole('button', { name: /Agentic Widget/i }).first();
        await expect(agenticWidgetFilter).toBeVisible({ timeout: 10000 });
        await agenticWidgetFilter.click();

        const targetAsset = page.getByText(/CDR based fraud prevention playbook/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent widget marketplace purchase: CDR based fraud prevention playbook', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const agenticWidgetFilter = page.getByRole('button', { name: /Agentic Widget/i }).first();
        await expect(agenticWidgetFilter).toBeVisible({ timeout: 10000 });
        await agenticWidgetFilter.click();

        await openAssetPurchase('CDR based fraud prevention playbook', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show chain marketplace asset: Decision Analyzer', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceChainDecision);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const chainFilter = page.getByRole('button', { name: /Chain of Agent/i }).first();
        await expect(chainFilter).toBeVisible({ timeout: 10000 });
        await chainFilter.click();

        const targetAsset = page.getByText(/Decision Analyzer/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent chain marketplace purchase: Decision Analyzer', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const chainFilter = page.getByRole('button', { name: /Chain of Agent/i }).first();
        await expect(chainFilter).toBeVisible({ timeout: 10000 });
        await chainFilter.click();

        await openAssetPurchase('Decision Analyzer', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show chain marketplace asset: CdrAnalysisChain', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceChainCdr);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const chainFilter = page.getByRole('button', { name: /Chain of Agent/i }).first();
        await expect(chainFilter).toBeVisible({ timeout: 10000 });
        await chainFilter.click();

        const targetAsset = page.getByText(/CdrAnalysisChain/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent chain marketplace purchase: CdrAnalysisChain', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const chainFilter = page.getByRole('button', { name: /Chain of Agent/i }).first();
        await expect(chainFilter).toBeVisible({ timeout: 10000 });
        await chainFilter.click();

        await openAssetPurchase('CdrAnalysisChain', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show chain marketplace asset: FullcycleSalesAccelerator', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceChainSales);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const chainFilter = page.getByRole('button', { name: /Chain of Agent/i }).first();
        await expect(chainFilter).toBeVisible({ timeout: 10000 });
        await chainFilter.click();

        const targetAsset = page.getByText(/FullcycleSalesAccelerator/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent chain marketplace purchase: FullcycleSalesAccelerator', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const chainFilter = page.getByRole('button', { name: /Chain of Agent/i }).first();
        await expect(chainFilter).toBeVisible({ timeout: 10000 });
        await chainFilter.click();

        await openAssetPurchase('FullcycleSalesAccelerator', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show utility marketplace asset: Case management utility', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceUtilityCase);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const utilityFilter = page.getByRole('button', { name: /Utilities/i }).first();
        await expect(utilityFilter).toBeVisible({ timeout: 10000 });
        await utilityFilter.click();

        const targetAsset = page.getByText(/Case management utility/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent utility marketplace purchase: Case management utility', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const utilityFilter = page.getByRole('button', { name: /Utilities/i }).first();
        await expect(utilityFilter).toBeVisible({ timeout: 10000 });
        await utilityFilter.click();

        await openAssetPurchase('Case management utility', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show utility marketplace asset: InsightTable Manager', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceUtilityInsight);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const utilityFilter = page.getByRole('button', { name: /Utilities/i }).first();
        await expect(utilityFilter).toBeVisible({ timeout: 10000 });
        await utilityFilter.click();

        const targetAsset = page.getByText(/InsightTable Manager/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent utility marketplace purchase: InsightTable Manager', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const utilityFilter = page.getByRole('button', { name: /Utilities/i }).first();
        await expect(utilityFilter).toBeVisible({ timeout: 10000 });
        await utilityFilter.click();

        await openAssetPurchase('InsightTable Manager', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show utility marketplace asset: feedback analysis', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceUtilityFeedback);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const utilityFilter = page.getByRole('button', { name: /Utilities/i }).first();
        await expect(utilityFilter).toBeVisible({ timeout: 10000 });
        await utilityFilter.click();

        const targetAsset = page.getByText(/feedback analysis/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent utility marketplace purchase: feedback analysis', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const utilityFilter = page.getByRole('button', { name: /Utilities/i }).first();
        await expect(utilityFilter).toBeVisible({ timeout: 10000 });
        await utilityFilter.click();

        await openAssetPurchase('feedback analysis', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show curated data marketplace asset: Customer Data Set', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceCuratedCustomer);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const curatedFilter = page.getByRole('button', { name: /Curated Data/i }).first();
        await expect(curatedFilter).toBeVisible({ timeout: 10000 });
        await curatedFilter.click();

        const targetAsset = page.getByText(/Customer Data Set/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent curated data marketplace purchase: Customer Data Set', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const curatedFilter = page.getByRole('button', { name: /Curated Data/i }).first();
        await expect(curatedFilter).toBeVisible({ timeout: 10000 });
        await curatedFilter.click();

        await openAssetPurchase('Customer Data Set', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show media marketplace asset: Case documents', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceMediaCaseDocs);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const mediaFilter = page.getByRole('button', { name: /Media/i }).first();
        await expect(mediaFilter).toBeVisible({ timeout: 10000 });
        await mediaFilter.click();

        const targetAsset = page.getByText(/Case documents/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent media marketplace purchase: Case documents', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const mediaFilter = page.getByRole('button', { name: /Media/i }).first();
        await expect(mediaFilter).toBeVisible({ timeout: 10000 });
        await mediaFilter.click();

        await openAssetPurchase('Case documents', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

    test('should show model marketplace asset: Hospital Resource Utilization Model', async () => {
        const previousCount = await chatPage.getReceivedMessageCount();
        await chatPage.sendMessage(B3_CHAT_PROMPTS.marketplaceModelHospital);
        await chatPage.waitForNewReceivedMessage(previousCount);

        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const modelFilter = page.getByRole('button', { name: /Model/i }).first();
        await expect(modelFilter).toBeVisible({ timeout: 10000 });
        await modelFilter.click();

        const targetAsset = page.getByText(/Hospital Resource Utilization Model/i).first();
        await targetAsset.scrollIntoViewIfNeeded();
        await expect(targetAsset).toBeVisible({ timeout: 20000 });
    });

    test('should prevent model marketplace purchase: Hospital Resource Utilization Model', async () => {
        const marketplaceHeading = await chatPage.getMarketplaceWidget();
        await expect(marketplaceHeading).toBeVisible({ timeout: 20000 });

        await ensureMarketplaceExpanded(page, marketplaceHeading);

        const modelFilter = page.getByRole('button', { name: /Model/i }).first();
        await expect(modelFilter).toBeVisible({ timeout: 10000 });
        await modelFilter.click();

        await openAssetPurchase('Hospital Resource Utilization Model', page);

        const unlimitedUseOption = page.getByRole('button', { name: /Unlimited use/i }).first();
        await expect(unlimitedUseOption).toBeVisible({ timeout: 15000 });
        await unlimitedUseOption.click();

        const confirmPurchaseButton = page.getByRole('button', { name: /^Purchase$/i }).first();
        await expect(confirmPurchaseButton).toBeVisible({ timeout: 15000 });
        await confirmPurchaseButton.click();

        await expectPurchaseError(page);

        await closeProductViewPopup(page);
        await chatPage.clearChatAndCanvas();
    });

});
