// @ts-nocheck
/**
 * E2E — Ofertas [Experimental] con columnas NULL en maeofe
 *
 * Regresión del 2026-08-03: `maeofe.listas` es nullable y en bases con ofertas
 * viejas llega como null. `listasFormatter` hacía row.listas.split(',') sin
 * verificar y rompía el render de la grilla; `modificar()` hacía lo mismo con
 * fila.listas y moría antes de llamar a cargarDetalle(), así que el detalle de
 * la oferta no se dibujaba (se veía como "faltan las columnas oferta / por cada
 * / se dará").
 *
 * Configurable por entorno:
 *   E2E_OFERTA_LISTAS_NULL  id de una oferta con `listas` NULL (suele ser vieja)
 *   E2E_OFERTA_BONIFICACION id de una oferta de bonificación CON detalle cargado
 */

import { test, expect } from '../fixtures/fixtures';

const OFERTA_LISTAS_NULL = process.env.E2E_OFERTA_LISTAS_NULL || '115';
const OFERTA_BONIFICACION = process.env.E2E_OFERTA_BONIFICACION || '2999';
const RUTA = 'oferta/ofertasBootstrap';

/** Errores de JS acumulados durante la corrida. */
function vigilarErrores(page) {
  const errores: string[] = [];
  page.on('pageerror', (e) => errores.push('pageerror: ' + String(e)));
  page.on('console', (m) => {
    if (m.type() === 'error') errores.push('console.error: ' + m.text());
  });
  return errores;
}

/**
 * Sale del filtro "Activas" y pinta TODAS las ofertas en una sola página.
 * Así el formatter de cada columna se ejecuta sobre las 168 filas, incluidas
 * las que tienen `listas` NULL — que es justamente lo que reventaba.
 */
async function mostrarTodas(page) {
  await page.selectOption('#estado', 'T');
  await page.waitForFunction(
    () => {
      const m = /de\s+(\d+)\s+filas/.exec(document.body.innerText);
      return m && Number(m[1]) > 10;
    },
    null,
    { timeout: 60000 }
  );
  await page.evaluate(() => {
    (window as any).$('#table').bootstrapTable('refreshOptions', { pageSize: 500 });
  });
  await page.waitForFunction(
    () => document.querySelectorAll('#table tbody tr').length > 100,
    null,
    { timeout: 60000 }
  );
}

/** Abre una oferta con el mismo clic que haría el usuario. */
async function abrirOferta(page, idoferta) {
  const fila = page.locator('#table tbody tr').filter({
    has: page.locator(`td:text-is("${idoferta}")`),
  });
  await expect(fila, `debe estar visible la oferta ${idoferta}`).toHaveCount(1);
  await fila.locator('a.modificar').click();
}

async function entrar(page, appPage) {
  await appPage.login(
    process.env.E2E_ADMIN_USER || 'mb.99',
    process.env.E2E_ADMIN_PASSWORD || ''
  );
  await page.goto(RUTA, { waitUntil: 'domcontentloaded' });
  await page.waitForSelector('#table tbody tr', { timeout: 60000 });
}

test.describe('Ofertas [Experimental] — columnas NULL', () => {
  test('la grilla pinta todas las ofertas, incluidas las de listas NULL', async ({ page, appPage }) => {
    const errores = vigilarErrores(page);
    await entrar(page, appPage);

    // Las ofertas con `listas` NULL son viejas: hay que salir del filtro "Activas".
    await mostrarTodas(page);

    const fila = page.locator(`#table tbody tr[data-uniqueid="${OFERTA_LISTAS_NULL}"]`);
    await expect(fila, `debe aparecer la oferta ${OFERTA_LISTAS_NULL}`).toHaveCount(1);

    // NULL es "sin definir", no "todas las listas": la celda queda vacía.
    // La posición se busca por el data-field del encabezado en vez de fijar nth(8):
    // así el test sigue valiendo si se reordenan, agregan u ocultan columnas.
    const idxListas = await page.locator('#table thead th').evaluateAll(
      (ths) => ths.findIndex((th) => th.getAttribute('data-field') === 'listas')
    );
    expect(idxListas, 'la grilla debe tener la columna listas').toBeGreaterThanOrEqual(0);
    const celdaListas = fila.locator('td').nth(idxListas);
    await expect(celdaListas).toHaveText('');

    expect(errores, 'no debe haber errores de JS:\n' + errores.join('\n')).toEqual([]);
  });

  test('el modal de una oferta con listas NULL abre y carga su detalle', async ({ page, appPage }) => {
    const errores = vigilarErrores(page);
    await entrar(page, appPage);
    await mostrarTodas(page);

    // Clic real en "Editar" de esa fila, igual que el usuario.
    // Si modificar() revienta a mitad, nunca se llama a cargarDetalle().
    await abrirOferta(page, OFERTA_LISTAS_NULL);
    await expect(page.locator('#editModal')).toBeVisible({ timeout: 30000 });
    await page.waitForSelector('#tableDetalle tbody tr', { timeout: 60000 });
    expect(await page.locator('#tableDetalle tbody tr').count()).toBeGreaterThan(0);

    expect(errores, 'no debe haber errores de JS:\n' + errores.join('\n')).toEqual([]);
  });

  test('una oferta de bonificación muestra oferta / por cada / se dará en el detalle', async ({ page, appPage }) => {
    const errores = vigilarErrores(page);
    await entrar(page, appPage);

    await abrirOferta(page, OFERTA_BONIFICACION);
    await expect(page.locator('#editModal')).toBeVisible({ timeout: 30000 });
    await page.waitForSelector('#tableDetalle tbody tr', { timeout: 60000 });

    for (const campo of ['oferta', 'porcada', 'sedara']) {
      await expect(
        page.locator(`#tableDetalle th[data-field="${campo}"]`),
        `debe existir la columna ${campo}`
      ).toHaveCount(1);
    }

    await page.screenshot({ path: 'playwright-report/ofertas-bonificacion-detalle.png', fullPage: true });
    expect(errores, 'no debe haber errores de JS:\n' + errores.join('\n')).toEqual([]);
  });
});
