import { expect, type Locator, type Page } from '@playwright/test';
import { BasePage } from './BasePage';
import { IAppointmentDetails } from '@business-logic/types/CustomerDetails';
import { formatDate, formatTime } from '@impl/utils/DateUtils';
import { ServiceLocation } from '@business-logic/types/Enums';
import { getCustomerDetails, ITestData } from 'safelite-playwright-core';

export class SchedulePage extends BasePage {
    readonly page: Page;
    issPageValue = 'schedule-page';

    readonly inShopButton: Locator;
    readonly mobileButton: Locator;
    readonly moreLocationsButton: Locator;
    readonly zipCodeTextBox: Locator;
    readonly findButton: Locator;
    readonly selectAShopOptions: Locator;
    readonly firstAppointmentButton : Locator;
    readonly firstAvailableAMDate: Locator;
    readonly firstAvailablePMDate: Locator;
    readonly firstAvailableTime: Locator;
    readonly firstAvailabeAMTime: Locator;
    readonly modalContinueButton: Locator;
    readonly dropOffButton: Locator;
    readonly dateText: Locator;
    readonly viewMoreDatesLink: Locator;

    readonly continueButton: Locator;

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

        this.inShopButton = this.page.locator('[buttonlabel="At a Safelite shop"]');
        this.mobileButton = this.page.locator('[buttonlabel="Have Safelite come to me"]');
        // For in shop
        this.moreLocationsButton = this.page.getByRole('button', { name: 'More Locations' });
        // For mobile
        this.zipCodeTextBox = this.page.locator('#serviceZipCode');
        this.findButton = this.page.getByRole('button', { name: 'Find' });
        // For in-shop and drop off
        this.selectAShopOptions = this.page.locator('[class="shop-question"]');
        this.firstAppointmentButton = this.page.locator('#availabilityIndicator').first();
        this.firstAvailableAMDate = this.page.locator('morning-row-cell has-appointments selected-date').first();
        this.firstAvailablePMDate = this.page.locator('afternoon-row-cell has-appointments selected-date').first();
        this.firstAvailableTime = this.page.locator('.time-slot-button').first();
        this.firstAvailabeAMTime = this.page.locator('.time-slot-button').nth(0);
        this.modalContinueButton = this.page.locator('#modalbtn');
        this.dropOffButton = this.page.locator('[class="dropoff-label"]');
        this.dateText = this.page.locator('[class="modal-header mb-2 mt-2"]');
        this.viewMoreDatesLink = this.page.getByRole('button', { name: 'More Right arrow icon' });

        this.continueButton = this.page.locator('#stacked').locator('button:has-text("Continue")');
    }

    // Select in shop and schedule
    async scheduleInShop(appointmentDetails?: IAppointmentDetails){
        
        if (appointmentDetails?.serviceLocation === ServiceLocation.InShop) {
           try {await this.inShopButton.waitFor({ state: 'visible', timeout: 5000 });
            await this.inShopButton.isVisible()
            await this.inShopButton.click();
            await (await this.getFirstNonDropOffTimeSlot()).click();
        } catch {
            await this.inShopButton.isHidden() 
            await (await this.getFirstNonDropOffTimeSlot()).click();
        }    
        } else if (appointmentDetails?.serviceLocation === ServiceLocation.DropOff) {
            if (await this.inShopButton.isVisible()){
            await this.inShopButton.waitFor({ state: 'visible', timeout: 5000 });
            await this.inShopButton.click();

            if (await this.dropOffButton.isVisible()) {
                await this.dropOffButton.waitFor({ state: 'visible', timeout: 5000 });
                await this.dropOffButton.click()
            } else {
                await (await this.getFirstNonDropOffTimeSlot()).click();
            }
            } else {
                await (await this.getFirstNonDropOffTimeSlot()).click();
            }
        } else {
            await this.selectFirstAvailableTime();
        }
        await this.continueButton.click();
    }

    // Select mobile button, enter zip code, click find button, select first available time and continue
    async scheduleMobile(appointmentDetails: IAppointmentDetails){
        await this.mobileButton.click();
        await this.zipCodeTextBox.fill(appointmentDetails.serviceAddress!.postalCode!);
        await this.findButton.click();
        await this.selectFirstAvailableTime();
        await this.continueButton.click();
    }

    // Selects the first available time slot but if its not visible, click "More" first to load more dates and times
    async selectFirstAvailableTime(): Promise<void> {
        if (await this.firstAvailableTime.isVisible()) {
            await this.firstAvailableTime.click();
        } else {
            await this.viewMoreDatesLink.click();
            await this.firstAvailableTime.waitFor({ state: 'visible' });
            await this.firstAvailableTime.click();
        }
    }

    async getFirstNonDropOffTimeSlot(): Promise<Locator> {
        const timeSlots = this.page.locator('.time-slot-button');
        const nonDropOff = timeSlots.filter({ hasNotText: /Drop & Go/i });
        return nonDropOff.first();
    }
}