import { expect, type Locator, type Page } from '@playwright/test';
import { BasePage } from './BasePage';
import { ServicePackage, VehicleDamage } from '@business-logic/types/Enums';
import { PaymentMethod } from '@business-logic/types/Enums';

export class ServicePackagesPage extends BasePage {
    readonly page: Page;
    readonly standardPackageButton: Locator;
    readonly premiumPackageButton: Locator;
    readonly glassOnlyButton: Locator;
    readonly payOnMyOwnButton: Locator;
    readonly paywithInsuranceButton: Locator;
    readonly iHavePromoCodeButton: Locator;

    //Your quote is almost ready modal
    readonly skipQuoteEmailButton: Locator;
    readonly emailInput: Locator;
    readonly getMyQuoteButton: Locator;
    readonly closeButton: Locator;
    url = process.env['BASE_URL']! + '/fmg/?fmgPage=quote';

    //Enter a promo code modal
    readonly promoCodeTextbox: Locator;
    readonly applyPromoButton: Locator;

    readonly repeatedClicksModalCloseButton: Locator;


    constructor(page: Page) {
        super(page);
        this.page = page;
        this.standardPackageButton = this.page.getByText('Standard');
        this.premiumPackageButton = this.page.getByText('Premium');
        this.glassOnlyButton = this.page.getByText('Glass service only', { exact: true });
        this.payOnMyOwnButton = this.page.locator('label').filter({ hasText: 'Pay on my own' }).locator('div');
        this.paywithInsuranceButton = this.page.locator('label').filter({ hasText: 'Pay with insurance' }).locator('div');
        this.iHavePromoCodeButton = this.page.getByRole('link', { name: 'I have a promo code' });
        this.skipQuoteEmailButton = this.page.getByRole('button', { name: 'Skip' });
        this.emailInput = this.page.getByRole('textbox', { name: 'Enter your email address' });
        this.getMyQuoteButton = this.page.getByRole('button', { name: 'Get my quote' });
        this.closeButton = this.page. getByRole('dialog').locator('button').filter({ hasText: 'Close' });
        this.promoCodeTextbox = this.page.getByLabel('Enter a promo code');
        this.applyPromoButton = this.page.getByRole('button', { name: 'Apply promo code' });
        this.repeatedClicksModalCloseButton = this.page.locator('.QSISlider').locator('img[src*=\'close\']');

        // this.validateURL(this.url);
    }

    async selectPaymentMethod(method: PaymentMethod): Promise<void> {
        const locators = {
            [PaymentMethod.Insurance]: this.paywithInsuranceButton,
            [PaymentMethod.SelfPay]: this.payOnMyOwnButton
        }

        await locators[method].click();
    }

    async selectServicePackage(servicePackage: ServicePackage): Promise<void> {
        const locators = {
            [ServicePackage.GlassOnly]: this.glassOnlyButton,
            [ServicePackage.Premium]: this.premiumPackageButton,
            [ServicePackage.Standard]: this.standardPackageButton,
        }

        if (servicePackage != null) {
            await locators[servicePackage].click();
        } 
    }

    async handleQuotePopup(email?: string): Promise<void> {
        await this.emailInput.waitFor({ state: 'visible' });
        if (await this.emailInput.isVisible()) {
            if (email) {
                await this.emailInput.fill(email);
                await this.getMyQuoteButton.click();
                if (await this.repeatedClicksModalCloseButton.isVisible()) {
                    await this.repeatedClicksModalCloseButton.click();
                }
                await this.page.waitForTimeout(3000);
                await this.closeButton.click();

            } else {
                await this.skipQuoteEmailButton.click();
            }
        }
    }

    async enterPromo(promoCode: string): Promise<void> {
        await this.iHavePromoCodeButton.click();
        await this.promoCodeTextbox.fill(promoCode);
        await this.applyPromoButton.click();
    }
    
    async verifyCanNotRecal(): Promise<boolean> {
        // Get Vuex state from localStorage
        const vuexState = JSON.parse(await this.page.evaluate('localStorage.getItem(\'vuex\')'));

        // Validate in the backend to make sure the can safelite recalibrate data is correct
        if (vuexState.order?.lineItems?.glassParts?.length > 0) {
            for (const glassPart of vuexState.order.lineItems.glassParts) {
                await expect(glassPart.canSafeliteRecalibrate).toBe(false);
                await expect(glassPart.requiresRecalibration).toBe(true);
            }
            return true;
        }
        return false;
    }

    async verifyDynamicRecal(): Promise<void> {
        // Get Vuex state from localStorage
        const vuexState = JSON.parse(await this.page.evaluate('localStorage.getItem(\'vuex\')'));
    
        // Validate in the backend to make sure the dynamic recalibration part is present
        if (vuexState.order?.lineItems?.glassParts?.length > 0) {
            const hasDynamicRecalPart = vuexState.order.lineItems.glassParts.some(glassPart =>
                glassPart.childParts.some(childPart =>
                    childPart.partNumber.includes("RECAL DYNAMIC")
                )
            );
    
            await expect(hasDynamicRecalPart).toBe(true);
            console.log("Recal part line item is verified");
        } else {
            throw new Error("No glass parts found in the order");
        }
    }

    async verifyIsRepair(isRepair: boolean, vehicleDamage: VehicleDamage[]): Promise<void> {
        // Get Vuex state from localStorage
        const vuexState = JSON.parse(await this.page.evaluate('localStorage.getItem(\'vuex\')'));

        // Validate in the backend to make sure isRepair is aligned with the data
        if (isRepair) {
            await expect(vuexState.order.damage.isRepair).toBe(true);

            // Check the number of chips based on vehicleDamage array
            if (vehicleDamage.includes(VehicleDamage.WindshieldOneChip)) {
                await expect(vuexState.order.damage.numberOfChips).toBe(1);
            }
            if (vehicleDamage.includes(VehicleDamage.WindshieldTwoChips)) {
                await expect(vuexState.order.damage.numberOfChips).toBe(2);
            }
            if (vehicleDamage.includes(VehicleDamage.WindshieldThreeChips)) {
                await expect(vuexState.order.damage.numberOfChips).toBe(3);
            }
        } else {
            await expect(vuexState.order.damage.isRepair).toBe(false);
        }
    }
    

    async verifyVehicleParts(vehicleDamage: VehicleDamage[]): Promise<void> {
        // Get Vuex state from localStorage
        const vuexState = JSON.parse(await this.page.evaluate('localStorage.getItem(\'vuex\')'));
    
        // Validate the presence of specific parts in the glassParts array
        const glassParts = vuexState.order?.lineItems?.glassParts;
    
        if (glassParts?.length > 0) {
            for (const partType of vehicleDamage) {
                const hasPartType = glassParts.some(glassPart => glassPart.partType === partType);
                await expect(hasPartType, `Expected part type: ${partType}`).toBe(true);
            }
        } else {
            throw new Error("No glass parts found in the order");
        }
    }

    async verifyOEMPart(): Promise<void> {
        // Get Vuex state from localStorage
        const vuexState = JSON.parse(await this.page.evaluate('localStorage.getItem(\'vuex\')'));
    
        // Validate the presence of an OEM part
        if (vuexState.order?.lineItems?.glassParts?.length > 0) {
            const firstGlassPartNumber = vuexState.order.lineItems.glassParts[0].partNumber;
    
            await expect(firstGlassPartNumber.includes("OEM")).toBe(true);
        } else {
            throw new Error("No glass parts found in the order");
        }
    }
}