import { expect, type Locator, type Page } from '@playwright/test';
import { BasePage } from './BasePage';
import { IAppointmentDetails } from '@business-logic/types/CustomerDetails';
import { ServiceLocation } from '@business-logic/types/Enums';
import { AddressForm } from './forms/AddressForm';
import { faker } from '@faker-js/faker';

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 saveAddressButton: Locator;

    issPageValue = 'service-location';

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

        this.addressForm = new AddressForm(page);

        // Initial selection
        this.inShopButton = this.page.locator('[buttonlabel="In-shop"]');
        this.mobileButton = this.page.locator('[buttonlabel="Mobile"]')
        this.dropOffButton = this.page.locator('[buttonlabel="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('div').filter({ hasText: /Appts/}).first();
        this.firstAppointmentButton = this.page.locator('#availabilityIndicator').first();
        this.changeZipButton = this.page.locator('[id="serviceZipLinkPromptId"]');
        this.updateZipTextBox = this.page.getByRole('textbox', { name: 'Update your service ZIP code'});
        this.saveZipButton = this.page.getByRole('button', { name: 'Save ZIP code' });


        // 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.saveAddressButton = this.page.getByRole('button', { name: 'Save Address' });
    }

    async selectLocation(appointmentDetails: IAppointmentDetails){
        if (appointmentDetails.alternateServiceZip) {
            await this.changeZipButton.click();
            await this.fillAndValidate(this.updateZipTextBox, appointmentDetails.alternateServiceZip);
            await this.saveZipButton.click();
        }

        switch(appointmentDetails.serviceLocation) {
            case ServiceLocation.Mobile: 
                await this.scheduleMobile(appointmentDetails);
                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) {
            await this.selectAShopOptions.locator(`[buttonbodycopy="${appointmentDetails.shopAddress}"]`).check();
        } else {
            await this.firstAppointmentButton.click(); 
        }
    }

    async scheduleMobile(appointmentDetails: IAppointmentDetails){
        if (appointmentDetails.serviceAddress) {
            await this.mobileButton.click();
            await this.enterServiceAddressButton.click();
            await this.addressForm.populateAddress({ address: appointmentDetails.serviceAddress! });
            if (faker.datatype.boolean()) {
                await this.vehicleProtectedYesButton.check();
            } else {
                await this.vehicleProtectedNoButton.check();
            }
            await this.saveAddressButton.click();
        } 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(); 
        }
    }

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

    }
}