import { Page } from "@playwright/test"
import { DashboardPage } from "./dashboard.page"
import { normalizeAddress } from "./utils/utlisFunc";
import { infoClientPreview } from "./client/client.snapshot";

type ClientEntry = {
    address_1: string;
    address_2: string;
    avatar: string;
    birthday: string | null;
    city: string;
    created_at: string;
    email_address: string;
    first_name: string;
    full_address: string;
    full_name: string;
    gender: string;
    id: string;
    is_archived: boolean;
    last_name: string;
    note: string;
    phone_number: string;
    state_code: string;
    tags: string[];
    updated_at: string;
    zip_code: string;
}

type ClientStat = {
    entries: {
        total: number;
        data: ClientEntry[];
    };
    archived_entries: {
        total: number;
        data: ClientEntry[];
    };
}

type InfoClient = {
    first_name?: string;
    last_name?: string;
    dob?: string;
    phone?: string;
    gender?: string;
    email?: string;
    address_1?: string;
    address_2?: string;
    city?: string;
    state?: string;
    zip_code?: string;
    tags?: string;
    createAnotherClient?: boolean;
}

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

    get clientLoc() {
        return {
            optionInSelect: (option: string) => this.genLoc(`//div[text()='${option}']/ancestor::li[@class='dropdown-item']`),
            mainContainer: this.genLoc(`//div[@id='root']`),
            heading: this.genLoc(`//div[@id='root']//span[contains(text(), '${this.businessPlural}')]`),
            btnNewClient: this.genLoc(`//div[@id='root']//button[contains(text(), 'New ${this.businessSingular}')]`),
            newClientDialog: this.genLoc(`//div[not(@id) and contains(@class, 'modal-dialog') and .//h3[text()='New ${this.businessSingular}']]`),
            btnCancel: this.genLoc(`//div[contains(@class, 'modal-dialog') and .//h3[text()='New ${this.businessSingular}']]//div[contains(@class, 'modal-footer')]//button[contains(@class, 'btn-cancel')]`),
            headerFilter: this.genLoc("//h3[text()='Filter']"),
            // List
            personalSearch: this.genLoc(`//div[contains(@class, 'personal-search')]`),
            perPageInput: this.genLoc(`//input[@name='per_page']`),
            btnFilter: this.genLoc(`//button[contains(@class, 'btn-filter')]`),
            inputSearch: this.genLoc(`//div[contains(@class, 'personal-search')]//input[@placeholder='Search...']`),
            noResult: this.genLoc(`//div[contains(text(), 'Create a new patient') or contains(text(), 'No matching results found. Try again.')]`),
            filterDialog: {
                container: this.genLoc(`//div[contains(@class, 'modal-content') and .//h3[contains(normalize-space(),'Filter')]]`),
                name: this.genLoc(`//input[@placeholder='Enter ${this.businessSingular} Name']`),
                created: this.genLoc(`//input[@name='created']`),
                updated: this.genLoc(`//input[@name='updated']`),
                tag: this.genLoc(`//input[@name='name_tags']`),

                iconClose: this.genLoc(`//div[contains(@class, 'modal-content') and .//h3[contains(normalize-space(),'Filter')]]//button[contains(@class, 'btn-close')]`),
                btnClose: this.genLoc(`//div[contains(@class, 'modal-content') and .//h3[contains(normalize-space(),'Filter')]]//div[contains(@class, 'modal-footer')]//button[text()='Cancel']`),
                btnReset: this.genLoc(`//div[contains(@class, 'modal-content') and .//h3[contains(normalize-space(),'Filter')]]//div[contains(@class, 'modal-footer')]//button[text()='Reset']`),
                btnApply: this.genLoc(`//div[contains(@class, 'modal-content') and .//h3[contains(normalize-space(),'Filter')]]//div[contains(@class, 'modal-footer')]//button[text()='Apply']`),
            },

            customizedColumnDialog: {
                container: this.genLoc(`//div[contains(@class, 'modal-content') and .//h3[contains(normalize-space(),'Customized Columns')]]`),
                checkboxItem: (name: string) => this.genLoc(`//input[@name='${name}' and @type='checkbox']`),
                checkboxMap: {
                    'Gender': 'gender',
                    'Email Address': 'email_address',
                    'Updated': 'updated_at',
                    'Created': 'created_at',
                },
                btnApply: this.genLoc(`//div[contains(@class, 'modal-content') and .//h3[contains(normalize-space(),'Customized Columns')]]//div[contains(@class, 'modal-footer')]//button[text()='Apply']`),
            },

            // Threedot setting
            btnThreedot: this.genLoc(`//div[@class='dropdown d-flex align-items-center']`),
            customizedColumnMenu: this.genLoc(`//span[contains(@class, 'dropdown-item') and normalize-space()='Customized Columns']`),
            archivedClient: this.genLoc(`//span[contains(@class, 'dropdown-item') and normalize-space()='Archived ${this.businessSingular}']`),
            unarchivedClient: this.genLoc(`//span[contains(@class, 'dropdown-item') and normalize-space()='Unarchived ${this.businessSingular}']`),
            modalCustomizedColumn: this.genLoc(`//div[contains(@class, 'modal-content') and .//h3[contains(normalize-space(),'Customized Columns')]]`),
            iconCloseModalCustomizedColumn: this.genLoc(`//div[contains(@class, 'modal-content') and .//h3[contains(normalize-space(),'Customized Columns')]]//button[contains(@class, 'btn-close')]`),

            // Filter block
            filterBlock: this.genLoc(`//div[contains(@class, 'show-filter')]`),
            archivedClientFilter: this.genLoc(`//div[contains(@class, 'actions-list') and contains(normalize-space(), 'Archive')]`),

            // Client Form
            newClientForm: this.genLoc(`(//div[@class='modal-content'])[4]`),
            btnCloseNewClientForm: this.genLoc(`(//div[@class='modal-content'])[4]/div/child::button`),
            inputFirstNameNewClient: this.genLoc(`//input[@name='first_name']`),
            inputLastNameNewClient: this.genLoc(`//input[@name='last_name']`),
            inputDobNewClient: this.genLoc(`//input[@name='birthday' and @inputmode='numeric']`),
            inputPhoneNewClient: this.genLoc(`//input[@name='phone_number' and @inputmode='numeric']`),
            inputGenderNewClient: this.genLoc(`//input[@name='gender' and contains(@class,'form-control')]`),
            inputEmailNewClient: this.genLoc(`//input[@type='email']`),
            inputAddressNewClient: this.genLoc(`//input[@name='address_1']`),
            inputSuiteNewClient: this.genLoc(`//input[@name='address_2']`),
            inputCityNewClient: this.genLoc(`//input[@name='city']`),
            inputStateNewClient: this.genLoc(`//input[@name='state_code']`),
            inputZipNewClient: this.genLoc(`//input[@name='zip_code']`),
            inputTagsNewClient: this.genLoc(`//input[@name='tags']`),
            btnCreateNewClient: this.genLoc(`//button[@type='button' and normalize-space()='Create']`),
            checkboxCreateAnotherClient: this.genLoc(`//input[contains(@id,'checkbox-create_contact')]`),
            btnUpdateInPopupClientDetail: this.genLoc(`(//div[@class='modal-content'])[2]/descendant::button[text()='Update']`),
            btnArchiveClientDetail: this.genLoc(`//button[text()='Archive']`),
            btnUnarchiveClientDetail: this.genLoc(`//button[text()='Unarchive']`),
            btnYesArchiveClientDetail: this.genLoc(`//button[text()='Yes']`),
            btnLeave: this.genLoc("//button[text()='Leave']"),

            // Manage
            clientSearch: this.genLoc(`//input[contains(@placeholder,'Search.') and @class='form-control']`),
            msgNoClientFound: this.genLoc(`//div[contains(text(),'No matching results found. Try again.') or contains(text(),'Create a new patient.')]`),

            // Patient Detail
            btnUpdateClientDetail: this.genLoc(`//div[contains(@class,'box-btn-activity-share')]/button[text()='Update']`),
            clientName: this.genLoc(`//span[contains(@class,'business-contact-name')]`),
            clientDob: this.genLoc(`(//div[@class='list-info-items']/span)[1]`),
            clientPhone: this.genLoc(`(//div[@class='list-info-items']/span)[3]`),
            clientGender: this.genLoc(`(//div[@class='list-info-items']/span)[4]`),
            clientAddress: this.genLoc(`(//div[@class='list-info-items']/span)[6]`),
            btnBack: this.genLoc(`//button[text()='Back']`),
            listTag: this.genLoc(`//p[contains(@class,'request-tag-child')]`),

            // Notification
            notificationAddNewClientSuccess: this.genLoc(`//p[contains(text(),'Added New Successfully!')]`),
            notificationUpdateClientSuccess: this.genLoc(`//p[contains(text(),'Updated Successfully!')]`),
            notificationArchiveClientSuccess: this.genLoc(`//p[contains(text(),'Archived Successfully!')]`),
            btnClosePopupNotification: this.genLoc(`//button[@class='my-snackbar__close']`),
            notificationDuplicateClient: this.genLoc(`//p[contains(text(),'Your input partially matches an existing record. To prevent duplicates, please provide addition details. Here is what you provided:')]`),

            //
            dataInTableClient: (name: string) => this.genLoc(`//a[text()='${name}']`),

            //Detail Client
            detail: {
                lableNameCreateRequest: this.genLoc("//label[@class='select-step-value select-step-2 cl-gray']"),
                dropdownOptionAddNew: this.genLoc("//span[@class='dropdown-item cursor-pointer']"),
                threeDotsBtn: this.genLoc("//div[@class='dropdown d-flex align-items-center']"),
                tabName: (tabName: string) => this.genLoc(`//p[@class='tab-name' and text()='${tabName}']`),
                inputByName: (name: string) => this.genLoc(`//input[@name='${name}']`),
            }
        }
    }

    get clientSnapshot() {
        return {
            infoClientPreview: infoClientPreview
        }
    }

    get clientConst() {
        return {
            tableColumns: {
                'name': 'full_name',
                'dob': 'birthday',
                'phone': 'phone_number',
                'address': 'full_address'
            }
        }
    }

    async open() {
        await this.page.goto('clients')
    }

    async initialStats(): Promise<ClientStat> {
        const stats = await this.page.request.get(`clients?return_type=json&per_page=100&page=1&is_archived=false`);
        const archivedStats = await this.page.request.get(`clients?return_type=json&per_page=100&page=1&is_archived=true`);

        const statResponse = await stats.json();
        const archivedStatResponse = await archivedStats.json();

        return {
            entries: {
                total: statResponse.total,
                data: statResponse.data
            },
            archived_entries: {
                total: archivedStatResponse.total,
                data: archivedStatResponse.data
            }
        }
    }

    async getDataByApi(orderByColumn: string, perPage: number, page: number, isArchived: boolean, direction: string): Promise<ClientEntry[]> {
        const rows = await this.page.request.get(`clients?return_type=json&per_page=${perPage}&page=${page}&is_archived=${isArchived}&sort=${orderByColumn}&direction=${direction}`);
        const response = await rows.json();
        return response.data;
    }

    async createNewClient(infoClient: InfoClient) {
        await this.clientLoc.inputFirstNameNewClient.fill(infoClient.first_name ?? '');
        await this.clientLoc.inputLastNameNewClient.fill(infoClient.last_name ?? '');
        await this.clientLoc.inputDobNewClient.fill(infoClient.dob ?? '');
        await this.clientLoc.inputPhoneNewClient.fill(infoClient.phone ?? '');

        await this.clientLoc.inputGenderNewClient.fill(infoClient.gender ?? '');
        await this.page.click(`//div[contains(text(),'${infoClient.gender}')]`);

        await this.clientLoc.inputEmailNewClient.fill(infoClient.email ?? '');
        await this.clientLoc.inputAddressNewClient.fill(infoClient.address_1 ?? '');
        await this.clientLoc.inputSuiteNewClient.fill(infoClient.address_2 ?? '');
        await this.clientLoc.inputCityNewClient.fill(infoClient.city ?? '');

        await this.clientLoc.inputStateNewClient.fill(infoClient.state ?? '');
        await this.page.click(`//div[contains(text(),'${infoClient.state}')]`);

        await this.clientLoc.inputZipNewClient.fill(infoClient.zip_code ?? '');
        await this.clientLoc.inputTagsNewClient.fill(infoClient.tags ?? '');
        if (infoClient.tags) {
            await this.page.click(`//div[contains(text(),'${infoClient.tags}')]`);
        }
        await this.page.mouse.click(0,0);
        await this.clientLoc.checkboxCreateAnotherClient.setChecked(infoClient.createAnotherClient ?? false);
        await this.page.mouse.click(0,0);
        await this.clientLoc.btnCreateNewClient.click();
    }

    getXpathClientInfoBy(firstName: string, lastName: string, dob: string, phone: string, address: string): { name: string, dob: string, phone: string, address: string } {
        return {
            name: `//td[2]/a[contains(text(),'${firstName} ${lastName}')]`,
            dob: `//td/a[contains(text(),'${firstName} ${lastName}')]/parent::td/following-sibling::td/a[contains(text(),'${dob}')]`,
            phone: `//td/a[contains(text(),'${firstName} ${lastName}')]/parent::td/following-sibling::td/a[contains(text(),'${phone}')]`,
            address: `//td/a[contains(text(),'${firstName} ${lastName}')]/parent::td/following-sibling::td/a[contains(text(),'${normalizeAddress(address)}')]`
        };
    }

    async deleteClient(firstName: string, lastName: string) {
        await this.clientLoc.clientSearch.fill(`${firstName} ${lastName}`);
        await this.page.waitForTimeout(1000);
        await this.page.click(`//td[2]/a[contains(text(),'${firstName} ${lastName}')]`);
        await this.clientLoc.btnUpdateClientDetail.click();
        await this.clientLoc.btnArchiveClientDetail.click();
        await this.clientLoc.btnYesArchiveClientDetail.click();
    }

    async updateInfoClient(infoClient: InfoClient) {
        await this.dashboardLoc.buttonByText("Update").first().click();
        await this.clientLoc.inputFirstNameNewClient.fill(infoClient.first_name ?? '');
        await this.clientLoc.inputLastNameNewClient.fill(infoClient.last_name ?? '');
        await this.clientLoc.inputDobNewClient.fill(infoClient.dob ?? '');
        await this.clientLoc.inputPhoneNewClient.fill(infoClient.phone ?? '');
        await this.clientLoc.inputGenderNewClient.fill(infoClient.gender ?? '');
        await this.clientLoc.inputEmailNewClient.fill(infoClient.email ?? '');
        await this.clientLoc.inputAddressNewClient.fill(infoClient.address_1 ?? '');
        await this.clientLoc.inputSuiteNewClient.fill(infoClient.address_2 ?? '');
        await this.clientLoc.inputCityNewClient.fill(infoClient.city ?? '');
        await this.clientLoc.inputStateNewClient.fill(infoClient.state ?? '');
        await this.clientLoc.inputZipNewClient.fill(infoClient.zip_code ?? '');
        await this.clientLoc.inputTagsNewClient.fill(infoClient.tags ?? '');
        await this.page.click(`//div[contains(text(),'${infoClient.tags}')]`);
        await this.dashboardLoc.modal.headerModal("Patient Detail").click();
        await this.dashboardLoc.buttonByText("Update").nth(1).click();
    }

    async clickClientDetail(firstName: string, lastName: string) {
        await this.clientLoc.clientSearch.fill(`${firstName} ${lastName}`);
        await this.page.waitForTimeout(1000); // TODO: wait for data load. Fix me later
        await this.page.click(`//td[2]/a[contains(text(),'${firstName} ${lastName}')]`);
        await this.page.waitForTimeout(1000); // TODO: wait for data load. Fix me later
    }
}