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

/**
 * Select a gender option from the gender combobox using keyboard navigation (ArrowDown + Enter).
 * Works with both native <select> elements and custom combobox inputs.
 *
 * @param page - Playwright page object
 * @param genderValue - One of: "Male", "Female", "Other", "Prefer not to say"
 */
export async function selectGenderWithKeyboard(page: Page, genderValue: string): Promise<void> {
  // Find the gender select or input (try multiple selectors)
  const genderSelect = page.locator('select').filter({ hasText: /gender/i }).or(
    page.locator('select').filter({ has: page.locator('option[value="Male"]') })
  );

  const genderInput = page.locator('input[placeholder*="gender" i], input[placeholder*="Select" i]');

  const selectVisible = await genderSelect.isVisible().catch(() => false);
  const inputVisible = await genderInput.isVisible().catch(() => false);

  if (selectVisible) {
    // Native <select> - use selectOption as fallback if keyboard doesn't work
    const optionValues: Record<string, string> = {
      'Male': 'Male',
      'Female': 'Female',
      'Other': 'Other',
      'Prefer not to say': 'Prefer not to say',
    };
    const value = optionValues[genderValue];
    if (value) {
      await genderSelect.selectOption(value);
    }
  } else if (inputVisible) {
    // Custom combobox input - click to open dropdown
    await genderInput.click();

    // Build the option selector based on the gender value
    // For DashboardDesignPreview-style dropdowns, options appear in a list
    // Try to find and click the matching option
    const optionLocator = page.locator(`text="${genderValue}"`).first();
    const optionVisible = await optionLocator.isVisible().catch(() => false);

    if (optionVisible) {
      await optionLocator.click();
    } else {
      // Fallback: type the value and press Enter
      await genderInput.fill(genderValue);
      await genderInput.press('Enter');
    }
  }
}

/**
 * Select a gender option using direct JavaScript value injection via page.evaluate.
 * This bypasses the UI and directly sets the value in the DOM/state.
 *
 * @param page - Playwright page object
 * @param genderValue - One of: "Male", "Female", "Other", "Prefer not to say"
 * @param fieldKey - The field key, defaults to "gender"
 */
export async function setGenderViaJS(page: Page, genderValue: string, fieldKey = 'gender'): Promise<void> {
  // Try native select first
    const nativeSelectWorked = await page.evaluate((value: string) => {
    const selects = Array.from(document.querySelectorAll('select'));
    for (const sel of selects) {
      const options = Array.from(sel.options).map((o: HTMLOptionElement) => o.value);
      if (options.includes(value)) {
        sel.value = value;
        sel.dispatchEvent(new Event('change', { bubbles: true }));
        return true;
      }
    }
    return false;
  }, genderValue);

  if (!nativeSelectWorked) {
    // Try custom combobox - inject into input value and trigger input event
    await page.evaluate((value: string) => {
      const inputs = Array.from(document.querySelectorAll('input'));
      for (const input of inputs) {
        const placeholder = input.getAttribute('placeholder') || '';
        if (placeholder.toLowerCase().includes('gender') || placeholder.toLowerCase().includes('select')) {
          input.value = value;
          input.dispatchEvent(new Event('input', { bubbles: true }));
          input.dispatchEvent(new Event('change', { bubbles: true }));
          return;
        }
      }
    }, genderValue);
  }
}

/**
 * Select gender using keyboard ArrowDown + Enter sequence.
 * This is the preferred approach for custom comboboxes.
 *
 * @param page - Playwright page object
 * @param genderValue - The gender option to select
 */
export async function selectGenderArrowDownEnter(page: Page, genderValue: string): Promise<void> {
  // Find gender field - try select first, then input
  let genderField: Locator | null = null;
  let isSelect = false;

  try {
    const selectLocator = page.locator('select');
    if (await selectLocator.isVisible()) {
      genderField = selectLocator;
      isSelect = true;
    }
  } catch {
    // not visible
  }

  if (!genderField) {
    // Try input with placeholder matching gender or Select
    const inputs = page.locator('input');
    const count = await inputs.count();
    for (let i = 0; i < count; i++) {
      const input = inputs.nth(i);
      const placeholder = await input.getAttribute('placeholder').catch(() => '');
      if (placeholder && (placeholder.toLowerCase().includes('gender') || placeholder.toLowerCase().includes('select'))) {
        if (await input.isVisible()) {
          genderField = input;
          break;
        }
      }
    }
  }

  if (!genderField) {
    throw new Error('Gender field not found on page');
  }

  if (isSelect) {
    // For native select: click to focus, then ArrowDown + Enter
    await genderField.click();
    await genderField.press('ArrowDown');
    await genderField.press('Enter');
  } else {
    // For custom combobox: click to open dropdown list
    await genderField.click();

    // Wait briefly for dropdown to appear
    await page.waitForTimeout(300);

    // Press ArrowDown to navigate to the option
    await genderField.press('ArrowDown');

    // Press Enter to select
    await genderField.press('Enter');
  }
}
