/**
 * Smart Form Filler helper for cPad tests.
 *
 * Detects all interactive form controls on a page (or within a locator scope)
 * and fills them with sensible test values so form-validation tests do not
 * need to enumerate every field manually.
 *
 * Supported field types:
 *   text, email, number, url, tel, search, password, date, time, textarea,
 *   checkbox, radio, select, file (skipped)
 *
 * Hidden fields and readonly fields are ignored.
 */

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

/** Seed text used for text-like inputs */
const RANDOM_TEXT  = `Test_${Date.now()}`;
const RANDOM_EMAIL = 'playwright-test@test.com';
const RANDOM_NUM   = '42';
const RANDOM_URL   = 'https://skinbase.test';
const RANDOM_DATE  = '2025-01-01';
const RANDOM_TIME  = '09:00';
const RANDOM_TEXTAREA = `Automated test content generated at ${new Date().toISOString()}.`;

/**
 * Fill all detectable form controls inside `scope` (defaults to the whole page).
 *
 * @param page  Playwright Page object (used for evaluate calls)
 * @param scope Optional Locator to restrict filling to a specific container
 */
export async function fillForm(page: Page, scope?: Locator): Promise<void> {
  const root: Page | Locator = scope ?? page;

  // ── text / email / url / tel / search / password / date / time ──────────
  const textInputs = root.locator(
    'input:not([type=hidden]):not([type=submit]):not([type=button])' +
    ':not([type=reset]):not([type=file]):not([type=checkbox]):not([type=radio])' +
    ':not([readonly]):not([disabled])',
  );

  const inputCount = await textInputs.count();
  for (let i = 0; i < inputCount; i++) {
    const input = textInputs.nth(i);
    const type  = (await input.getAttribute('type'))?.toLowerCase() ?? 'text';
    const name  = (await input.getAttribute('name')) ?? '';

    // Skip honeypot / internal fields whose names suggest they must stay empty
    if (/honeypot|_token|csrf/i.test(name)) continue;

    try {
      await input.scrollIntoViewIfNeeded();

      switch (type) {
        case 'email':
          await input.fill(RANDOM_EMAIL);
          break;
        case 'number':
        case 'range':
          await input.fill(RANDOM_NUM);
          break;
        case 'url':
          await input.fill(RANDOM_URL);
          break;
        case 'date':
          await input.fill(RANDOM_DATE);
          break;
        case 'time':
          await input.fill(RANDOM_TIME);
          break;
        case 'password':
          await input.fill(`Pw@${Date.now()}`);
          break;
        default:
          await input.fill(RANDOM_TEXT);
      }
    } catch {
      // Field might have become detached or invisible — skip silently
    }
  }

  // ── textarea ─────────────────────────────────────────────────────────────
  const textareas = root.locator('textarea:not([readonly]):not([disabled])');
  const taCount   = await textareas.count();
  for (let i = 0; i < taCount; i++) {
    try {
      await textareas.nth(i).scrollIntoViewIfNeeded();
      await textareas.nth(i).fill(RANDOM_TEXTAREA);
    } catch { /* skip */ }
  }

  // ── select ────────────────────────────────────────────────────────────────
  const selects = root.locator('select:not([disabled])');
  const selCount = await selects.count();
  for (let i = 0; i < selCount; i++) {
    try {
      // Pick the first non-empty option
      const firstOption = await selects.nth(i).locator('option:not([value=""])').first().getAttribute('value');
      if (firstOption !== null) {
        await selects.nth(i).selectOption(firstOption);
      }
    } catch { /* skip */ }
  }

  // ── checkboxes (toggle unchecked → checked) ───────────────────────────────
  const checkboxes = root.locator('input[type=checkbox]:not([disabled])');
  const cbCount    = await checkboxes.count();
  for (let i = 0; i < cbCount; i++) {
    try {
      const isChecked = await checkboxes.nth(i).isChecked();
      if (!isChecked) {
        await checkboxes.nth(i).check();
      }
    } catch { /* skip */ }
  }
}

/**
 * Detect whether the given scope contains a visible, submittable form.
 * Returns true if any <form>, submit button, or text input is found.
 */
export async function hasForm(scope: Page | Locator): Promise<boolean> {
  const formCount   = await scope.locator('form').count();
  const submitCount = await scope.locator('button[type=submit], input[type=submit]').count();
  const inputCount  = await scope.locator('input:not([type=hidden])').count();
  return formCount > 0 || submitCount > 0 || inputCount > 0;
}
