import { Browser, BrowserContext, expect, Locator, Page } from '@playwright/test';
import { DashboardPage } from './dashboard.page';
import { LoginPage } from './login.page';
import { modalCompareRequest, modalManuallyLinkCase, turnOffAllNotificationEmail, turnOffAllNotificationInApp, turnOnAllNotificationEmail, turnOnAllNotificationInApp } from './share-request/share-request.snapshot';
import { extractVerificationCode } from '../utils/mail';

export class SharedRequestPage extends DashboardPage {
    constructor(page: Page) {
        super(page);
    }

    statusTests = [
        { detail: 'Inquiry', expectedStatus: 'Open' },
        { detail: 'Awaiting', expectedStatus: 'Open' },
        { detail: 'Preparing', expectedStatus: 'In Progress' },
        { detail: 'Need LoP', expectedStatus: 'Open' },
        { detail: 'Verbal Approval', expectedStatus: 'In Progress' },
        { detail: 'On Hold', expectedStatus: 'On Hold' },
        { detail: '+ 3 LoP Attempts', expectedStatus: 'On Hold' },
        { detail: 'On Hold / 3 + Attempt', expectedStatus: 'On Hold' },
        { detail: 'Processed', expectedStatus: 'Closed' },
        { detail: 'Provided', expectedStatus: 'Closed' },
        { detail: 'Accepted', expectedStatus: 'Closed' },
        { detail: 'Cancelled', expectedStatus: 'Closed' },
        { detail: 'Declined', expectedStatus: 'Closed' },
        { detail: 'LoP on File', expectedStatus: 'Closed' }
    ];

    async open() {
        await this.page.goto('/shared/requests', { waitUntil: 'domcontentloaded' });
    }

    get shareRequestLoc() {
        return {
            linkcase: {
                requestIDIntable: this.genLoc("//tr[contains(@class,'not_field_read')][1]/td[2]/a/span"),
                rowUnread: this.genLoc("//tr[contains(@class,'not_field_read')]"),
                requestNewID: (requestID: string) => this.genLoc(`//a[contains(.,'${requestID}')]/descendant::span[text()='${requestID}']`),
            },

            btnCancelModal: this.genLoc("//button[@data-test-id='btn-modal-filter-modal-form-cancel']"),
            btnResetModal: this.genLoc("//button[@data-test-id='btn-modal-filter-modal-form-reset']"),
            boxTextBusiness: (value: string) => this.genLoc(`//div[@class='box-text box-text-business']/div[text()='${value}']`),
            btnSubmitMessage: this.genLoc("//button[@data-test-id='btn-modal-respond-snapshot-submit']"),
            titleDiscussion: (title: string) => this.genLoc(`//h4[@class='title mb-0']/span[text()='${title}']`),
            textEditorCreateCaseArea: this.genLoc("(//div[@class='jodit-react-container']/descendant::div[@class='jodit-wysiwyg'])[2]"),
            buttonRepond: this.genLoc("//a[text()='Respond']"),
            thumbImagePosted: this.genLoc("//div[@class='letter-thumb-image']"),
            detailPostedAttachment: this.genLoc(".tab-detail-attachment"),
            btnBackToReq: this.genLoc("//a[contains(.,'Back to request')]"),
            btnDelteMember: this.genLoc("//div[@class='btn-delete-share cursor-pointer']"),
            optionMember: (name: string) => this.genLoc(`//div[contains(@class,'title-option') and text()='${name}']`),
            tableRowTd: (data: string) => this.genLoc(`//td[text()='${data}']`),
            notification: {
                btnOpenModalNoti: this.genLoc("//button[contains(@class,'btn-soft-primary')]"),
                btnToggleSettingNoti: this.genLoc("//button[@class='accordion-button after-none collapsed']"),
                inputNotiByName: (name: string) => this.genLoc(`//input[@name='${name}']`),
                btnTurnOffAll: this.genLoc("//input[@id='checkbox-slide-turn-off-all-false']/parent::div"),
                btnTurnOnAll: this.genLoc("//input[@id='checkbox-slide-turn-off-all-true']/parent::div")
            },

            linkCase: {
                btnNext: this.genLoc("//button[@class='btn btn-primary w-fit-content']"),
                prevClient: this.genLoc("//span[@class='cl-gray-3 word-break']"),
                selectedDoi: this.genLoc("//span[contains(@class,'link-blue-2')]"),
                rowFieldDataReceiver: (field: string) => this.genLoc(`(//td[@class='table-compare__td table-compare__td--label' and text()='${field}']/ancestor::tr/descendant::td)[2]`),
                rowFieldDataSender: (field: string) => this.genLoc(`(//td[@class='table-compare__td table-compare__td--label' and text()='${field}']/ancestor::tr/descendant::td)[3]`),
                btnActionsReceiver: (field: string) => this.genLoc(`(//td[@class='table-compare__td table-compare__td--label' and text()='${field}']/ancestor::tr/descendant::td)[2]/descendant::span`),
                btnActionsSender: (field: string) => this.genLoc(`(//td[@class='table-compare__td table-compare__td--label' and text()='${field}']/ancestor::tr/descendant::td)[3]/descendant::span`),
                btnRapidChane: (field: string) => this.genLoc(`(//td[@class='table-compare__td table-compare__td--label' and text()='${field}']/ancestor::tr/descendant::td)[3]/div//*[name()='svg']`),
            }
        }
    }

    get shareRequestSnapshot() {
        return {
            turnOffAllNotificationInApp: turnOffAllNotificationInApp,
            turnOffAllNotificationEmail: turnOffAllNotificationEmail,
            turnOnAllNotificationInApp: turnOnAllNotificationInApp,
            turnOnAllNotificationEmail: turnOnAllNotificationEmail,
            dialogCompareRequest: modalCompareRequest,
            modalManuallyLinkCase: modalManuallyLinkCase
        }
    }

    get shareRequestProps() {
        return {
            filterProperties: [
                {
                    name: 'patient',
                    type: 'input'
                },
                {
                    name: 'from_business_name',
                    type: 'select'
                },
                {
                    name: 'to_business_name',
                    type: 'select'
                }
            ],
            threeDotDropdownMenus: {
                customizedColumn: 'Customized Columns',
            },
            customizedColumns: [
                {
                    name: 'Pin',
                    default: true,
                    tableDisplayName: 'Pin'
                },
                {
                    name: 'Request #',
                    default: true,
                    tableDisplayName: 'Request #'
                },
                {
                    name: 'Request Type',
                    default: true,
                    tableDisplayName: 'Request Type'
                },
                {
                    name: 'Client Name',
                    default: true,
                    tableDisplayName: 'Client Name'
                },
                {
                    name: 'Creator',
                    default: true,
                    tableDisplayName: 'Creator'
                },
                {
                    name: 'Directed To',
                    default: true,
                    tableDisplayName: 'Directed To'
                },
                {
                    name: 'Status',
                    default: true,
                    tableDisplayName: 'Status'
                },
                {
                    name: 'Status Details',
                    default: true,
                    tableDisplayName: 'Status Details'
                },
                {
                    name: 'Submitted User',
                    default: false,
                    tableDisplayName: 'Submitted User'
                },
                {
                    name: 'Received',
                    default: false,
                    tableDisplayName: 'Received'
                },
                {
                    name: 'Updated',
                    default: false,
                    tableDisplayName: 'Updated'
                }
            ]
        }
    }

    // Login as another user in a new browser context and return the new RequestPage
    async loginInAnotherBrowser(browser: Browser, username: string, password: string): Promise<{ context: BrowserContext; page: Page; sharedRequestPage: SharedRequestPage }> {
        const context = await browser.newContext();
        const page = await context.newPage();
        const loginPage = new LoginPage(page);
        await loginPage.open();
        await loginPage.login(username, password);
        await expect(loginPage.baseLoc.dashboardContainer).toBeVisible({ timeout: 15_000 });
        return { context, page, sharedRequestPage: new SharedRequestPage(page) };
    }

    async respondToRequest(message: string): Promise<void> {
        const textEditorBody = this.shareRequestLoc.textEditorCreateCaseArea;
        await this.shareRequestLoc.buttonRepond.waitFor({ state: 'visible' });
        await this.shareRequestLoc.buttonRepond.click({ force: true });
        await textEditorBody.waitFor({ state: 'visible' });
        await textEditorBody.type(message, { delay: 20 });
        await this.shareRequestLoc.btnSubmitMessage.click();
        await this.dashboardLoc.msgCreateSuccess.waitFor({ state: 'visible' });
        await textEditorBody.waitFor({ state: 'hidden' });
    }

    async verifyPostSnapshot(): Promise<void> {
        await this.shareRequestLoc.thumbImagePosted.first().waitFor({ state: 'visible' });
        await this.shareRequestLoc.thumbImagePosted.first().click();
        await this.waitForSecond(2);
    }

    async backToRequestList(): Promise<void> {
        if (await this.shareRequestLoc.btnBackToReq.isVisible()) {
            await this.shareRequestLoc.btnBackToReq.click();
        }
    }

    async openLinkAndCompletePasscode(sharedRequestPage: SharedRequestPage, requestCtx: any, buttonLocator: Locator): Promise<SharedRequestPage> {
        const buttonPage = await buttonLocator.elementHandle().then(el => el?.ownerFrame()).then(frame => frame?.page()) || buttonLocator.page();
        const [newPage] = await Promise.all([
            buttonPage.context().waitForEvent('page'),
            buttonLocator.click()
        ]);

        const newTabPage = new SharedRequestPage(newPage);
        await newTabPage.dashboardLoc.buttonByText("Next").click();
        await newTabPage.waitForSecond(3);

        const foundMail = await newTabPage.findMail(requestCtx);
        expect(foundMail).toBeTruthy();

        const verificationCode = extractVerificationCode(foundMail.Subject) || '';
        await newTabPage.dashboardLoc.inputCode.fill(verificationCode);
        await newTabPage.dashboardLoc.buttonByText("Next").click();

        return newTabPage;
    }

    async findMail(request: { get: (arg0: string) => any; }): Promise<any> {
        let mailUrl = process.env.MAIL_SERVER || 'http://69.28.90.112:8025/'
        // Call API to get mails
        const rawResponse = await request.get(`${mailUrl}/api/v1/messages`);
        expect(rawResponse.status()).toEqual(200);
        const response = await rawResponse.json();
        const messages = await response.messages;
        return messages[0];
    }
}
