import { type Page, type Locator, expect } from '@playwright/test';

export class RegistrationPage {
    readonly page: Page;

    // Modern auth flow from /sign-in
    readonly logInSignUpButton: Locator;
    readonly loginDialog: Locator;
    readonly loginEmailInput: Locator;
    readonly loginPasswordInput: Locator;
    readonly loginConfirmButton: Locator;
    readonly dontHaveAccountButton: Locator;
    readonly signUpEmailInput: Locator;
    readonly createPasswordInput: Locator;
    readonly reEnterPasswordInput: Locator;
    readonly signUpConfirmButton: Locator;
    readonly fullNameInput: Locator;
    readonly registerNowFinalButton: Locator;
    readonly businessUserOption: Locator;
    readonly individualUserOption: Locator;
    readonly accountContinueButton: Locator;

    // Legacy /welcome & /sign-up flow (kept for compatibility)
    readonly registerLink: Locator;
    readonly businessButton: Locator;
    readonly individualButton: Locator;
    readonly consumerButton: Locator;
    readonly creatorButton: Locator;
    readonly consumerAndCreatorButton: Locator;
    readonly passwordInput: Locator;
    readonly confirmPasswordInput: Locator;
    readonly businessNameInput: Locator;
    readonly websiteInput: Locator;
    readonly businessEmailInput: Locator;
    readonly firstNameInput: Locator;
    readonly lastNameInput: Locator;
    readonly individualEmailInput: Locator;
    readonly term1Checkbox: Locator;
    readonly term2Checkbox: Locator;
    readonly term3Checkbox: Locator;
    readonly registerNowButton: Locator;

    // Verification
    readonly verificationCodeInput: Locator;
    readonly verifyButton: Locator;

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

        // New flow locators
        this.logInSignUpButton = page.getByRole('button', { name: /Log In\/? Sign Up/i });
        this.loginDialog = page.getByRole('dialog', { name: /Welcome back!/i });
        this.loginEmailInput = page.locator(
            'input[placeholder="example@mail.com"], input[placeholder="Enter your email"], input[type="email"]'
        ).first();
        this.loginPasswordInput = page.locator(
            'input[placeholder="***********"], input[placeholder="Enter your password"], input[type="password"]'
        ).first();
        this.loginConfirmButton = this.loginDialog.getByRole('button', { name: 'Confirm' });
        this.dontHaveAccountButton = page.getByRole('button', { name: /Don't have an account\?/i });
        this.signUpEmailInput = page.getByRole('textbox', { name: 'Enter your email' });
        this.createPasswordInput = page.getByRole('textbox', { name: 'Create your password' });
        this.reEnterPasswordInput = page.getByRole('textbox', { name: 'Re-enter your password' });
        this.signUpConfirmButton = page.getByRole('button', { name: 'Confirm' });
        this.fullNameInput = page.getByRole('textbox', { name: 'Enter your full name' });
        this.registerNowFinalButton = page.getByRole('button', { name: /Register now/i });
        this.businessUserOption = page.getByRole('button', { name: /Business User/i });
        this.individualUserOption = page.getByRole('button', { name: /Individual user/i });
        this.accountContinueButton = page.getByRole('button', { name: /^Continue$/i });

        // Legacy locators retained
        this.registerLink = page
            .locator(
                "a[href='/welcome'], a[href*='sign-up'], button:has-text('Log In/ Sign Up'), button:has-text('Sign Up'), button:has-text('Register')"
            )
            .first();
        this.businessButton = page.locator('button', { hasText: 'Business' });
        this.individualButton = page.locator('button', { hasText: 'Individual usage' });
        this.consumerButton = page.locator('button').filter({ hasText: 'Consumer' }).first();
        this.creatorButton = page.locator('button').filter({ hasText: 'Creator' }).first();
        this.consumerAndCreatorButton = page.locator('button').filter({ hasText: 'Consumer & Creator' }).first();
        this.passwordInput = page.getByPlaceholder('Password', { exact: true });
        this.confirmPasswordInput = page.getByPlaceholder('Confirm password');
        this.businessNameInput = page.getByPlaceholder('Name', { exact: true });
        this.websiteInput = page.getByPlaceholder('Website');
        this.businessEmailInput = page.getByPlaceholder('Business email');
        this.firstNameInput = page.getByPlaceholder('First Name');
        this.lastNameInput = page.getByPlaceholder('Last Name (Optional)');
        this.individualEmailInput = page.getByPlaceholder('Email', { exact: true });
        this.term1Checkbox = page.locator('#term1');
        this.term2Checkbox = page.locator('#term2');
        this.term3Checkbox = page.locator('#term3');
        this.registerNowButton = page.locator('button', { hasText: 'Register Now' });

        // Verification screen has a single plain textbox and Verify button
        this.verificationCodeInput = page.locator('input[type="text"], input[type="tel"], input:not([type])').first();
        this.verifyButton = page.getByRole('button', { name: /^(Verify|Confirm)$/i });
    }

    async goto() {
        await this.page.goto('/');
    }

    async gotoSignIn() {
        await this.page.goto('/sign-in');
    }

    async openAuthDialog() {
        await this.gotoSignIn();
        const visibleDialog = this.page.getByRole('dialog');
        if (!(await visibleDialog.isVisible({ timeout: 1000 }).catch(() => false))) {
            await this.logInSignUpButton.click();
        }
        await expect(this.page.locator('body')).toContainText(/Welcome back|Continue with Google|Don't have an account/i, { timeout: 15000 });
    }

    async loginFromSignIn(email: string, password: string) {
        await this.openAuthDialog();
        const dialog = this.page.getByRole('dialog', { name: /Welcome back!/i }).first();
        const emailInput = dialog.locator('input[placeholder="example@mail.com"], input[type="email"]').first();
        const passwordInput = dialog.locator('input[placeholder="***********"], input[type="password"]').first();
        const confirmButton = dialog.getByRole('button', { name: /^Confirm$/i }).first();

        if (!(await emailInput.isVisible({ timeout: 5000 }).catch(() => false))) {
            const backToLogin = this.page.getByRole('button', { name: /Already have an account|Back to login|Log in/i }).first();
            if (await backToLogin.isVisible({ timeout: 2000 }).catch(() => false)) {
                await backToLogin.click();
            }
        }
        await expect(emailInput).toBeVisible({ timeout: 15000 });
        await emailInput.click();
        await emailInput.clear();
        await emailInput.type(email, { delay: 20 });
        await expect(emailInput).toHaveValue(email, { timeout: 5000 });

        await passwordInput.click();
        await passwordInput.clear();
        await passwordInput.type(password, { delay: 20 });
        await expect(passwordInput).toHaveValue(password, { timeout: 5000 });

        await confirmButton.click();
    }

    async openSignUpFromSignIn() {
        await this.openAuthDialog();
        await this.dontHaveAccountButton.click();
        await expect(this.signUpEmailInput).toBeVisible({ timeout: 15000 });
    }

    async submitSignUpCredentials(email: string, password: string) {
        await this.signUpEmailInput.fill(email);
        await this.createPasswordInput.fill(password);
        await this.reEnterPasswordInput.fill(password);
        await this.signUpConfirmButton.click();
    }

    async submitFullName(fullName: string) {
        await expect(this.fullNameInput).toBeVisible({ timeout: 15000 });
        await this.fullNameInput.click();
        if (!(await this.fullNameInput.isEditable())) {
            await this.fullNameInput.evaluate((el) => {
                if (el.hasAttribute('readonly')) {
                    el.removeAttribute('readonly');
                }
            });
        }
        if (await this.fullNameInput.isEditable()) {
            await this.fullNameInput.fill(fullName);
        }
        await expect(this.registerNowFinalButton).toBeEnabled({ timeout: 10000 });
        if (await this.registerNowFinalButton.isEnabled()) {
            await this.registerNowFinalButton.click();
            return;
        }
        throw new Error('Register now is disabled on full-name step; likely the account already exists or input is locked.');
    }

    async waitForVerificationScreen() {
        await expect(this.page.locator('body')).toContainText(
            /please check your email|confirmation was\s+sent|check you email/i,
            { timeout: 30000 }
        );
        await expect(this.verificationCodeInput).toBeVisible({ timeout: 10000 });
    }

    async startRegistration() {
        try {
            await this.registerLink.click({ timeout: 10000 });
        } catch {
            await this.page.goto('/sign-up?type=individual&profile=consumer_credit');
        }
    }

    async selectBusiness() {
        await this.businessButton.click();
    }

    async selectIndividual() {
        await this.individualButton.click();
    }

    async selectPreference(preference: 'Consumer' | 'Creator' | 'Both') {
        if (preference === 'Consumer') {
            await this.consumerButton.click();
        } else if (preference === 'Creator') {
            await this.creatorButton.click();
        } else {
            await this.consumerAndCreatorButton.click();
        }
    }

    async fillBusinessDetails(name: string, website: string, email: string, password: string) {
        await this.businessNameInput.fill(name);
        await this.websiteInput.fill(website);
        await this.businessEmailInput.fill(email);
        await this.passwordInput.fill(password);
        await this.confirmPasswordInput.fill(password);
        await this.acceptTerms();
    }

    async fillIndividualDetails(firstName: string, lastName: string, email: string, password: string) {
        await this.firstNameInput.fill(firstName);
        await this.lastNameInput.fill(lastName);
        await this.individualEmailInput.fill(email);
        await this.passwordInput.fill(password);
        await this.confirmPasswordInput.fill(password);
        await this.acceptTerms();
    }

    async acceptTerms() {
        if (!(await this.term1Checkbox.isChecked())) await this.term1Checkbox.click();
        if (!(await this.term2Checkbox.isChecked())) await this.term2Checkbox.click();
        if (!(await this.term3Checkbox.isChecked())) await this.term3Checkbox.click();
    }

    async submit() {
        await this.registerNowButton.click();
    }

    async enterVerificationCode(code: string) {
        await expect(this.verificationCodeInput).toBeVisible({ timeout: 10000 });
        await this.verificationCodeInput.fill(code);
    }

    async clickVerify() {
        await this.verifyButton.click();
    }

    async completeBusinessUserConsumerFlow() {
        await expect(this.businessUserOption).toBeVisible({ timeout: 30000 });
        await this.businessUserOption.click();
        await expect(this.accountContinueButton).toBeEnabled({ timeout: 10000 });
        await this.accountContinueButton.click();

        const consumerButton = this.page.getByRole('button', { name: /Consumer/i }).first();
        if (await consumerButton.isVisible({ timeout: 10000 }).catch(() => false)) {
            await consumerButton.click();
            await expect(this.accountContinueButton).toBeEnabled({ timeout: 10000 });
            await this.accountContinueButton.click();
        }
    }

    async completeIndividualUserFlow() {
        await expect(this.individualUserOption).toBeVisible({ timeout: 30000 });
        await this.individualUserOption.click();
        await expect(this.accountContinueButton).toBeEnabled({ timeout: 10000 });
        await this.accountContinueButton.click();
    }

    async waitForTipsOrOnboarding() {
        await expect(this.page.locator('body')).toContainText(
            /Traditional search engines return links|Welcome to RoboCorp|tips|Congratulation/i,
            { timeout: 30000 }
        );
    }

    async completeTipsAndNavigateToChat() {
        await expect(this.page.locator('body')).toContainText(/Here is tips how to use our platform/i, { timeout: 30000 });

        const skipTipsButton = this.page.getByRole('button', { name: /Skip for now/i });
        if (await skipTipsButton.isVisible({ timeout: 5000 }).catch(() => false)) {
            await skipTipsButton.click();
        } else {
            const continueBtn = this.page.getByRole('button', { name: /^Continue$/i });
            for (let i = 0; i < 3; i++) {
                if (await continueBtn.isVisible({ timeout: 3000 }).catch(() => false)) {
                    await continueBtn.click();
                    await this.page.waitForTimeout(250);
                }
            }
        }

        // A campaign/onboarding panel can still appear on chat UI; skip it if present.
        const chatSkipButton = this.page.getByRole('button', { name: /^Skip for now$/i });
        if (await chatSkipButton.isVisible({ timeout: 3000 }).catch(() => false)) {
            await chatSkipButton.click();
        }
    }

    async waitForChatUi() {
        await expect(this.page.getByPlaceholder('Ask anything...')).toBeVisible({ timeout: 30000 });
    }

    private async openUserDropdownMenu() {
        const toggles = this.page.getByRole('button', { name: /Toggle User Dropdown/i });
        const count = await toggles.count();
        for (let i = 0; i < Math.max(1, count); i++) {
            try {
                await toggles.nth(i).click({ timeout: 5000, force: true });
                return;
            } catch {
                // try next matching toggle if present
            }
        }
        throw new Error('Unable to open user dropdown menu.');
    }

    async logoutFromChatUi() {
        const chatSkipButton = this.page.getByRole('button', { name: /^Skip for now$/i });
        if (await chatSkipButton.isVisible({ timeout: 2000 }).catch(() => false)) {
            await chatSkipButton.click();
        }

        let loggedOutViaUi = false;
        try {
            await this.openUserDropdownMenu();

            let logoutAction = this.page.getByRole('button', { name: /log ?out|sign ?out/i }).first();
            if (!(await logoutAction.isVisible({ timeout: 3000 }).catch(() => false))) {
                logoutAction = this.page.getByRole('menuitem', { name: /log ?out|sign ?out/i }).first();
            }
            if (!(await logoutAction.isVisible({ timeout: 3000 }).catch(() => false))) {
                logoutAction = this.page.locator('text=/^\\s*(Log\\s*out|Logout|Sign\\s*out)\\s*$/i').first();
            }

            await expect(logoutAction).toBeVisible({ timeout: 10000 });
            await logoutAction.click();
            loggedOutViaUi = true;
        } catch {
            // Fallback for flaky/hidden dropdown: force a logged-out state.
            await this.page.context().clearCookies();
            await this.page.goto('/sign-in');
        }

        await expect(this.page.getByRole('button', { name: /Log In\/ Sign Up/i })).toBeVisible({ timeout: 30000 });
        if (!loggedOutViaUi) {
            await expect(this.page).toHaveURL(/\/sign-in/i, { timeout: 10000 });
        }
    }
}
