import test, { expect, type Locator, type Page } from '@playwright/test';
import axe from 'axe-core';
import { updateAccessibilityReport } from '@utils/ReportUtils';
import { error } from 'console';

declare global {
    interface Window {
        axe: typeof axe;
    }
}

export class BasePage {
    readonly page: Page;
    readonly continueButton: Locator;
    readonly pageSpinner: Locator;
    readonly buttonLoadSpin: Locator;

    constructor(page: Page) {
        this.page = page;
        this.continueButton = page.locator('[id="infoBox"]').getByRole('button');
        this.pageSpinner = page.getByRole('status');
        this.buttonLoadSpin = page.getByRole('alert');
    }

    async nextPage() {
        const startingUrl = this.page.url();
        let pageName = startingUrl.split('Page=')[1] || startingUrl;
        await this.validateAccessibility(pageName);
        await expect(async () => {
            const currentUrl = this.page.url();
            if (currentUrl === startingUrl) {
                await this.continueButton.click({ timeout: 1000 });
            }
            //this causes the schedule page to fail
            //await expect(this.buttonLoadSpin).toHaveCount(0, {timeout: 180000});
            expect(currentUrl).not.toEqual(startingUrl);          
        }).toPass({ timeout: 180_000 });
    }

    async waitForURL(url: string) {
        await expect(this.pageSpinner).toHaveCount(0, { timeout: 60000 });
        await this.page.waitForURL(url);
    }

    async fillAndValidate(element: Locator, value: string) {
        await expect(async () => {
            await element.clear();
            await element.fill(value);
            await expect(element).toHaveValue(value);
        }).toPass();
    }

    async validateAccessibility(pageName: string) {
        try {
            if (process.env.ENABLE_ACCESSIBILITY_TESTING !== 'true') {
                return;
            }

            // Inject axe-core script into the page
            await this.page.addScriptTag({ content: axe.source });

            // Run axe-core accessibility checks
            const results = await this.page.evaluate(async () => {
                return await window.axe.run();
            });

            // Attach the results to the test report
            test.info().attach(`Accessibility results for ${pageName}`, {
                body: JSON.stringify(results, null, 2),
                contentType: 'application/json'
            });

            // Update the HTML report with the findings
            updateAccessibilityReport(pageName, results);
        } catch (error) {
            console.warn(`Error running accessibility checks for ${pageName}: ${error}`);
        }
    }
    async clickWithRetry(element, page) {
        const timeout = 5000; // milli seconds
        const startTime = Date.now();
        while (Date.now() - startTime < timeout) {
            try {
                if (await element.isEnabled()) {
                    await element.click();
                    await element.keyboard.press('Tab');
                    return; // Exit loop if click succeeds
                }
            } catch (error) {
                // Ignore error and retry
            }
            await page.waitForTimeout(100); // Small delay before retrying
        }
        console.log(`Failed to click the the element within ${timeout/1000} seconds` + error);
    }
    
    async logReferralNumber() {
        let mainLocalStorage = JSON.parse(await this.page.evaluate('localStorage.getItem(\'main\')'));
        let referralNumber = mainLocalStorage.order.referralNumber as number;
        let referralSequenceNumber = mainLocalStorage.order.referralSequenceNumber as number;
        if (referralNumber == null) {
            for (let i = 1; i <= 20; i++) {
                if (!referralNumber == null) break;
                await this.page.waitForTimeout(500);
                mainLocalStorage = JSON.parse(await this.page.evaluate('localStorage.getItem(\'main\')'));
                referralNumber = mainLocalStorage.order.referralNumber as number;
                referralSequenceNumber = mainLocalStorage.order.referralSequenceNumber as number;
            }
        }

        await test.step(`Referral Number:${referralNumber} Referral Sequence Number:${referralSequenceNumber}`, async () => {
            console.log(`Referral Number:${referralNumber}`);
            console.log(`Referral Sequence Number:${referralSequenceNumber}`);
        });

    }

    async validateURL(issPageValue: string) {
        let pass = false;
        let currentUrl = this.page.url();
        pass = currentUrl.includes(issPageValue);
        const isBailout = currentUrl.includes('bailout-page');
        if(!pass && !isBailout) {
            await this.waitForURLToChange(currentUrl);
            currentUrl = this.page.url();
        }
        expect(currentUrl).toContain(issPageValue);
    }

    async waitForURLToChange(startingUrl: string) {
        await expect(async () => {
            const currentUrl = this.page.url();
            expect(currentUrl).not.toEqual(startingUrl);
        }).toPass({ timeout: 60_000 });
    }
}