import { expect, type Locator, type Page } from '@playwright/test';
import { BasePage } from './BasePage';
import { IAppointmentDetails } from 'safelite-playwright-core';
import { AppointmentTimeslot, ServiceLocation } from 'safelite-playwright-core';
import { ProgressBarPercentages } from 'framework/localTypes/Enums';
import { AddressForm } from './forms/AddressForm';
import { faker } from '@faker-js/faker';
import { step } from 'framework/localTypes/Step';
import { ITestData } from 'framework/TestData';

export class ServiceLocationPage extends BasePage {
    readonly page: Page;

    readonly addressForm: AddressForm;

    // Initial selection
    readonly inShopButton: Locator;
    readonly mobileButton: Locator;
    readonly dropOffButton: Locator;
    readonly RecalWarningMessage1: Locator;
    readonly RecalWarningMessage2: Locator;
    readonly militaryWarningMessage: Locator;

    // For in-shop and drop off
    readonly selectAShopOptions: Locator;
    readonly firstAppointmentButton: Locator;
    readonly changeZipButton: Locator;
    readonly updateZipTextBox: Locator;
    readonly saveZipButton: Locator;

    // For mobile
    readonly enterServiceAddressButton: Locator;
    readonly serviceAddressTextBox: Locator;
    readonly aptNumberTextBox: Locator;
    readonly cityTextBox: Locator;
    readonly stateDropDown: Locator;
    readonly zipCodeTextBox: Locator;
    readonly vehicleProtectedYesButton: Locator;
    readonly vehicleProtectedNoButton: Locator;
    readonly repeatedClicksModalCloseButton: Locator;

    constructor(page: Page) {
        super(page);
        this.page = page;

        this.addressForm = new AddressForm(page);

        // Initial selection
        this.inShopButton = this.page.getByText(/In-shop/);
        this.mobileButton = this.page.locator('label[buttonlabel="Mobile"]');
        this.dropOffButton = this.page.getByText(/Drop-off/);
        this.RecalWarningMessage1 = this.page.getByText(/We're not able to provide mobile service/);
        this.RecalWarningMessage2 = this.page.getByText(/advanced safety system recalibration needs to be done in our shop./);
        this.militaryWarningMessage = this.page.locator('[class*="widget-name-AlertMilitaryBaseZipWidget"]');

        // For in-shop and drop off
        this.selectAShopOptions = this.page.locator('[class="shop-question"]');
        this.firstAppointmentButton = this.page.locator('fieldset:has(legend#chooseShop)').locator('label').first();
        this.changeZipButton = this.page.locator('a:has(span.sr-only:has-text("edit zip code"))');
        this.updateZipTextBox = this.page.locator('#serviceZipCode');
        this.saveZipButton = this.page.getByText('Save ZIP code', { exact: true });


        // For mobile
        this.enterServiceAddressButton = this.page.getByRole('link', { name: 'Enter your service address ' });
        this.serviceAddressTextBox = this.page.getByRole('textbox', { name: 'Street Address' });
        this.aptNumberTextBox = this.page.getByRole('textbox', { name: 'Apt. number'});
        this.cityTextBox = this.page.getByRole('textbox', { name: 'City' });
        this.stateDropDown = this.page.getByRole('combobox', { name: 'State' });
        this.zipCodeTextBox = this.page.getByRole('textbox', { name: 'Zip code' });
        this.vehicleProtectedYesButton = this.page.locator('label').filter({ hasText: 'Yes' }).locator('div');
        this.vehicleProtectedNoButton = this.page.locator('label').filter({ hasText: 'No' }).locator('div');
        this.repeatedClicksModalCloseButton = this.page.locator('.QSISlider').locator('img[src*=\'close\']');
    }

    async selectLocation(testData: Partial<ITestData>) {
        const { appointmentDetails, customerDetails } = testData;

        switch(appointmentDetails?.serviceLocation) {
            case ServiceLocation.Mobile:
                await this.scheduleMobile(testData);
                break;
            case ServiceLocation.InShop:
                await this.scheduleInShop(appointmentDetails);
                break;
            case ServiceLocation.DropOff:
                await this.scheduleDropOff(appointmentDetails);
                break;
        }
    }

    async scheduleInShop(appointmentDetails?: IAppointmentDetails) {
        await this.inShopButton.click();
        if (appointmentDetails && appointmentDetails.shopAddress) {
            const zipCodeMatch = appointmentDetails.shopAddress.match(/\b\d{5}$/);
            if (zipCodeMatch) {
                const zipCode = zipCodeMatch[0];
                // Enter the ZIP code into the updateZipTextBox
                await this.changeZipButton.click();
                await this.page.waitForTimeout(500);
                await this.updateZipTextBox.fill(zipCode);
                await this.saveZipButton.click();
            }
            await this.inShopButton.click();
            await this.selectAShopOptions.locator(`[buttonbodycopy="${appointmentDetails.shopAddress}"]`).scrollIntoViewIfNeeded().then(() => this.selectAShopOptions.locator(`[buttonbodycopy="${appointmentDetails.shopAddress}"]`).click());
        } else {
            await this.firstAppointmentButton.scrollIntoViewIfNeeded().then(async () => {
                await this.firstAppointmentButton.click();
                if (appointmentDetails) {
                    appointmentDetails.shopAddress = await this.firstAppointmentButton.locator('.row-two').innerText();
                }
            });
        }
    }

    async scheduleMobile(testData: Partial<ITestData>) {
        const { appointmentDetails, customerDetails } = testData;
        if (appointmentDetails?.serviceAddress) {
            await this.mobileButton.click();
            // await this.enterServiceAddressButton.click();
            await this.addressForm.populateAddress({ address: appointmentDetails.serviceAddress! });
            if (await this.repeatedClicksModalCloseButton.isVisible()) {
               await this.repeatedClicksModalCloseButton.click();
            }
            if (faker.datatype.boolean()) {
                await this.vehicleProtectedYesButton.check();
            } else {
                await this.vehicleProtectedNoButton.check();
            }
            if (appointmentDetails.appointmentTimeSlot == AppointmentTimeslot.EarlyBird)
            {
                await this.mockScheduleResponseForEarlyBird(customerDetails!);
            }
        } else {
            console.error('ServiceLocationPage >> Please supply an address')
        }
    }

    async scheduleDropOff(appointmentDetails?: IAppointmentDetails){
        await this.dropOffButton.click();
        if (appointmentDetails && appointmentDetails.shopAddress) {
            await this.selectAShopOptions.locator(`[buttonbodycopy="${appointmentDetails.shopAddress}"]`).check();
        } else {
            // await this.firstAppointmentButton.click(); 
            // await this.clickWithRetry(this.firstAppointmentButton, this.page);
            await this.firstAppointmentButton.scrollIntoViewIfNeeded().then(async () => {
                await this.firstAppointmentButton.click();
                if (appointmentDetails) {
                    appointmentDetails.shopAddress = await this.firstAppointmentButton.locator('.row-two').innerText();
                }
            });
        }
    }

    async validateRecalWarning(){
        await expect(this.RecalWarningMessage1).toBeVisible();
        await expect(this.RecalWarningMessage2).toBeVisible();

    }

    @step("ServiceLocationPage >> Select service location: ")
    async handleServiceLocationPage(testData: Partial<ITestData>) {

        await this.validateProgressBar(ProgressBarPercentages.ServiceLocationPage);
        await this.selectLocation(testData);
        await this.nextPage();
    }
}