import { type Page } from '@playwright/test';
import { siteConfig } from '../config/siteConfig';
import { waitForHydration } from './cart-helpers';

/**
 * Login via the UI form at /en/sign-in.
 *
 * Page structure (production):
 *   textbox "email address" → email field
 *   textbox "password"      → password field
 *   button "SIGN IN"        → submit (inside main form area, not the tab)
 */
export async function loginViaUI(
    page: Page,
    email: string,
    password: string
): Promise<boolean> {
    await page.goto(siteConfig.routes.login, {
        waitUntil: 'domcontentloaded',
    });
    await page
        .waitForLoadState('networkidle')
        .catch(() => console.log('Network idle timeout on login page, continuing...'));
    await waitForHydration(page);

    // Fill email — the field has accessible name "email address"
    const emailInput = page.getByRole('textbox', { name: /email/i }).first();
    await emailInput.waitFor({ state: 'visible', timeout: 10000 }).catch(() => null);
    if (!(await emailInput.isVisible().catch(() => false))) {
        console.error('Email input not found on login page');
        return false;
    }
    await emailInput.fill(email);

    // Fill password — password inputs have type="password", not matched by getByRole('textbox')
    const passwordInput = page.locator('input[type="password"], textbox[name*="password" i]').first();
    await passwordInput.waitFor({ state: 'visible', timeout: 10000 }).catch(() => null);
    if (!(await passwordInput.isVisible().catch(() => false))) {
        console.error('Password input not found on login page');
        return false;
    }
    await passwordInput.fill(password);

    // Click SIGN IN button (the submit button inside the form, not the navigation tab)
    // The tab link says "SIGN IN" but the submit button also says "SIGN IN"
    // We target the button specifically
    const signInButton = page.locator('main button:has-text("SIGN IN"), main button:has-text("Sign In")').first();
    if (!(await signInButton.isVisible().catch(() => false))) {
        console.error('Sign In submit button not found');
        return false;
    }

    // Click and wait for response
    await Promise.all([
        page.waitForResponse(
            (resp) =>
                resp.url().includes('/auth/login') ||
                resp.url().includes('/graphql'),
            { timeout: 15000 }
        ).catch(() => null),
        signInButton.click(),
    ]);

    // Wait for navigation or state change
    await page.waitForTimeout(3000);

    // If still on sign-in page, login failed
    const currentUrl = page.url();
    if (currentUrl.includes('sign-in') || currentUrl.includes('login')) {
        // Login form still visible means login failed
        const formStillVisible = await signInButton.isVisible().catch(() => false);
        if (formStillVisible) return false;
    }

    return true;
}

/**
 * Register a new account at /en/create-account.
 *
 * Page structure (production):
 *   textbox "Family Name"    → family name
 *   textbox "First name"     → first name
 *   textbox "Email Address"  → email
 *   textbox "password"       → password (first one)
 *   textbox "confirm password" → confirm password
 *   button "REGISTER"        → submit
 */
export async function registerAccount(
    page: Page,
    details: {
        familyName: string;
        firstName: string;
        email: string;
        password: string;
    }
): Promise<boolean> {
    await page.goto(siteConfig.routes.register, {
        waitUntil: 'domcontentloaded',
    });
    await page
        .waitForLoadState('networkidle')
        .catch(() => console.log('Network idle timeout on register page, continuing...'));
    await waitForHydration(page);

    // Fill family name
    const familyName = page.getByRole('textbox', { name: /family name/i }).first();
    await familyName.waitFor({ state: 'visible', timeout: 10000 }).catch(() => null);
    if (!(await familyName.isVisible().catch(() => false))) {
        console.error('Family Name input not found');
        return false;
    }
    await familyName.fill(details.familyName);

    // Fill first name
    const firstName = page.getByRole('textbox', { name: /first name/i }).first();
    if (await firstName.isVisible().catch(() => false)) {
        await firstName.fill(details.firstName);
    }

    // Fill email
    const emailInput = page.getByRole('textbox', { name: /email/i }).first();
    if (await emailInput.isVisible().catch(() => false)) {
        await emailInput.fill(details.email);
    }

    // Fill password fields — password inputs have type="password", not matched by getByRole('textbox')
    const passwordInputs = page.locator('input[type="password"]');
    const pwCount = await passwordInputs.count();

    if (pwCount >= 1) {
        // First password field
        await passwordInputs.nth(0).fill(details.password);
    }
    if (pwCount >= 2) {
        // Confirm password field
        await passwordInputs.nth(1).fill(details.password);
    }

    // Click REGISTER button (the submit, not the tab link)
    const registerButton = page.locator('main button:has-text("REGISTER"), main button:has-text("Register")').first();
    if (!(await registerButton.isVisible().catch(() => false))) {
        console.error('Register submit button not found');
        return false;
    }

    await Promise.all([
        page.waitForResponse(
            (resp) =>
                resp.url().includes('/graphql') ||
                resp.url().includes('/auth') ||
                resp.url().includes('/customer'),
            { timeout: 20000 }
        ).catch(() => null),
        registerButton.click(),
    ]);

    await page.waitForTimeout(5000);

    // Check if we navigated away from create-account page
    const currentUrl = page.url();
    if (currentUrl.includes('create-account')) {
        // Still on register page — registration might have failed
        const formStillVisible = await registerButton.isVisible().catch(() => false);
        if (formStillVisible) return false;
    }

    return true;
}

/**
 * Check if the user is currently logged in.
 * On matsuyaginza.com, the header "Sign In" link changes when logged in.
 */
export async function isLoggedIn(page: Page): Promise<boolean> {
    // When logged in, the header account dropdown should show account-related links
    // instead of "Sign In" / "Create account"
    const signInLink = page.locator('header a[href*="sign-in"], banner a[href*="sign-in"]').first();
    const signInVisible = await signInLink.isVisible().catch(() => false);

    // If Sign In link is visible in header, user is NOT logged in
    if (signInVisible) return false;

    // Also check for logout/account indicators
    const loggedInIndicators = [
        'a[href*="/account"]:not([href*="login"]):not([href*="sign-in"]):not([href*="create"])',
        'a[href*="logout"]',
        'button:has-text("Log out")',
        'button:has-text("ログアウト")',
    ];

    for (const selector of loggedInIndicators) {
        const el = page.locator(selector).first();
        const visible = await el.isVisible().catch(() => false);
        if (visible) return true;
    }

    // If we can't find sign-in link OR account indicators,
    // check if we were redirected away from login page (indicates success)
    const url = page.url();
    return !url.includes('sign-in') && !url.includes('create-account');
}
