import test, { expect, type Locator, type Page } from '@playwright/test';
import { BasePage } from './BasePage';
import { ICustomerDetails, IVehicleDetails } from '@business-logic/types/CustomerDetails';
import { PaymentType, ServicePackage } from '@business-logic/types/Enums';
import { ITestData } from '@business-logic/types/ITestData';

export class OrderConfirmationPage extends BasePage {
    readonly page: Page;
    readonly serviceText: Locator;
    readonly emailText: Locator;
    readonly apptDateText: Locator;
    readonly amountDueText: Locator;
    readonly viewCartButton: Locator;
    readonly deductibleText: Locator;
    readonly subtotalText: Locator;
    readonly finalAmountDue: Locator;
    readonly cartServicePackageText: Locator;
    issPageValue = 'order-confirmation';

    constructor(page: Page) {
        super(page);
        this.page = page;
        this.serviceText = this.page.locator('[class="appointment-text text-center lh-base"]');
        this.emailText = this.page.locator('[class="email-confirmation-text"]');
        this.apptDateText = this.page.locator('[class="appointment-date-time text-center mt-4"]');
        this.amountDueText = this.page.getByLabel('expand cart details');
        this.viewCartButton = this.page.locator('#cart-dropdown-head');
        this.deductibleText = this.page.locator('#deductible-value');
        this.subtotalText = this.page.locator("#subtotal-value");
        this.finalAmountDue = this.page.locator('#bottom-amount-due-value');
        this.cartServicePackageText = this.page.locator('#cart-service-package');
    }

    async validateOrderConfirmationPage(testData: Partial<ITestData>) {
        // Destructure data we use
        const { vehicleDetails, customerDetails, servicePackage, isItac,
            isNoComp, isPolicyFound, claimDetails, paymentDetails, isUseVehicleOnPolicy } = testData;
        await this.serviceText.waitFor({ state: "visible" });
        await this.logOrderNumber();

        // Grab text
        const serviceTextValue = await this.serviceText.textContent();
        const apptDateValue = await this.apptDateText.textContent();
        const emailTextValue = await this.emailText.textContent();
        const servicePackageValue = await this.cartServicePackageText.textContent();
        const amountDueValue = await this.amountDueText.textContent();
        const deductibleTextValue = (isItac || isNoComp) ? null : await this.deductibleText.textContent();
        const subtotalTextValue = await this.subtotalText.textContent();
        const finalAmountDueValue = await this.finalAmountDue.textContent();

        // Extract service package price
        const servicePackageAmt = Number.parseFloat(servicePackageValue!.split('$')[1].replaceAll(',', ''));

        // General Validations
        expect.soft(serviceTextValue).toContain(`${vehicleDetails!.year} ${vehicleDetails!.make} ${vehicleDetails!.model}`);
        expect.soft(apptDateValue).toContain(customerDetails!.apptDate);
        expect.soft(emailTextValue).toContain(customerDetails!.email);

        // Service package validations
        await expect.soft(this.cartServicePackageText).toContainText(`${servicePackage}`)
        if ((servicePackage === ServicePackage.Premium && testData.isReplace === true) || servicePackage === ServicePackage.Standard) {
            expect.soft(servicePackageValue).toContain('New wiper blades');
        }
        if (servicePackage === ServicePackage.Premium) {
            expect.soft(servicePackageValue).toContain('Rain Defense™ treatment');
        }

        // Price validations
        if (servicePackage === ServicePackage.GlassOnly) {
            expect.soft(servicePackageAmt).toEqual(0);
        } else {
            expect.soft(servicePackageAmt).toBeGreaterThan(0);
        }

        if (isPolicyFound && (isUseVehicleOnPolicy ?? true)) {
            // Extract numbers
            const amountDueAmt = Number.parseFloat(amountDueValue!.split('$')[1].replaceAll(',', ''));
            const deductibleAmt = deductibleTextValue ? Number.parseFloat(deductibleTextValue.split('$')[1].replaceAll(',', '')) : 0;
            const subtotalAmt = Number.parseFloat(subtotalTextValue!.split('$')[1].replaceAll(',', ''));
            subtotalTextValue?.replaceAll(',', '')
            const finalAmountDueAmt = Number.parseFloat(finalAmountDueValue!.split('$')[1].replaceAll(',', ''));

            if (!(isItac || isNoComp)) {
                expect.soft(subtotalAmt).toEqual(claimDetails!.policyDeductible + servicePackageAmt);
                expect.soft(deductibleAmt).toEqual(claimDetails!.policyDeductible);
            } else {
                expect.soft(subtotalAmt).toBeGreaterThan(0);
                expect.soft(deductibleAmt).toEqual(0);
            }

            if (paymentDetails!.paymentType === PaymentType.PayAtService && (claimDetails!.policyDeductible > 0 || servicePackageAmt > 0)) {
                // Verify amount due > 0
                expect.soft(amountDueAmt).toBeGreaterThan(0);
                expect.soft(finalAmountDueAmt).toBeGreaterThan(0);
            } else {
                // Verify amount due 0
                expect.soft(amountDueAmt).toEqual(0);
                expect.soft(finalAmountDueAmt).toEqual(0);
            }
        } else {
            expect.soft(amountDueValue).toContain('Verifying coverage');
            expect.soft(subtotalTextValue).toEqual('Verifying coverage');
            expect.soft(finalAmountDueValue).toEqual('Verifying coverage');
        }
    }

    async logOrderNumber() {
        const sessionStorage = JSON.parse(await this.page.evaluate('sessionStorage.getItem(\'submittedOrder\')'));
        const workOrderNumber = sessionStorage.workOrderNumber;
        await test.step(`SessionStorage Work Order Number:${workOrderNumber}`, async () => {
            console.log(`SessionStorage Work Order Number:${workOrderNumber}`);
        });
    }
    
    async validateURL() {
        let pass = false;
        let currentUrl = this.page.url();
        pass = currentUrl.includes(this.issPageValue);
        while(!pass && currentUrl.includes('payment')) {
            await this.waitForURLToChange(currentUrl);
            currentUrl = this.page.url();
            pass = currentUrl.includes(this.issPageValue);
        }
        const isBailout = currentUrl.includes('bailout-page');
        if(!pass && !isBailout) {
            await this.waitForURLToChange(currentUrl);
            currentUrl = this.page.url();
        }
        expect(currentUrl).toContain(this.issPageValue);
    }
}