import { readFileSync } from 'node:fs';

import { describe, expect, it, vi } from 'vitest';

import { createInputTableRowClickHandler, getInputTableCellInteractionAttrs } from '../helpers/rowSelection';

// Exercise actual SFC handlers without loading unrelated stores and modal components.
const source = readFileSync('apps/jnpf-web-apps-main/src/components/Jnpf/InputTable/src/InputTable.vue', 'utf8');
const loaderSource = readFileSync('packages/jnpf/utils/src/helpers/common.ts', 'utf8');
const loader = new Function(`${loaderSource.match(/export function getScriptFunc\(str\) \{[\s\S]*?\n\}/)![0].replace('export ', '')}; return getScriptFunc;`)();
const functions = ['getCellClickHandler', 'onFormClick', 'getCellInteractionAttrs']
  .map((name) => source.match(new RegExp(`function ${name}\\([^]*?\\n\\}`))![0])
  .join('\n');

function harness(
  options: { disabled?: boolean; rowReadonly?: boolean; controlDisabled?: boolean; detailed?: boolean; displayOnly?: boolean; script?: string } = {},
) {
  const open = vi.fn();
  const field = {
    formId: 'directory',
    on: { click: options.script ?? '({ rowIndex, rowData, onlineUtils }) => onlineUtils.open(rowIndex, rowData)' },
    config: { __config__: { jnpfKey: 'input', isDisplayOnly: options.displayOnly } },
  };
  const rows = Array.from({ length: 25 }, (_, index) => ({ id: `row-${index}`, folder: '' }));
  const state = { tableFormData: rows.map(() => [field]), dataSource: rows, activeRowIndex: 0 };
  const getScopedParameter = vi.fn(() => ({ formData: { rows }, onlineUtils: { open } }));
  const handlers = new Function(
    'deps',
    `const { props, state, getRowReadonly, getConfById, getScriptFunc, getScopedParameter, getInputTableCellInteractionAttrs } = deps; ${functions}; return { onFormClick, getCellInteractionAttrs };`,
  )({
    props: { disabled: options.disabled },
    state,
    getRowReadonly: () => !!options.rowReadonly,
    getConfById: () => ({ readonly: true, disabled: options.controlDisabled, detailed: options.detailed }),
    getScriptFunc: loader,
    getScopedParameter,
    getInputTableCellInteractionAttrs,
  });
  return { ...handlers, state, rows, open, getScopedParameter };
}

describe('configured subtable click', () => {
  it('wires both native layouts and uses full row indexes in paginated tables', () => {
    expect(source).toContain('@click="onFormClick(index, cIndex, $event)"');
    expect(source).toContain('@click="onFormClick(getRealIndex(index), cIndex, $event)"');
  });
  it('runs once for a readonly input on page 3 without changing row selection', () => {
    const h = harness();
    const updateSelection = vi.fn();
    const row = document.createElement('div');
    const cell = document.createElement('div');
    const input = document.createElement('input');
    input.readOnly = true;
    Object.entries(h.getCellInteractionAttrs('directory', 23)).forEach(([key, value]) => cell.setAttribute(key, String(value)));
    row.append(cell);
    cell.append(input);
    const selection = createInputTableRowClickHandler({
      getRowKey: (r: { id: string }) => r.id,
      getSelectedRowKeys: () => [],
      getSelectedRows: () => [],
      isEnabled: () => true,
      isRowReadonly: () => false,
      updateSelection,
    });
    input.addEventListener('click', (event) => h.onFormClick(23, 0, event));
    row.addEventListener('click', selection(h.rows[23]).onClick);
    input.dispatchEvent(new MouseEvent('click', { bubbles: true }));
    expect(h.open).toHaveBeenCalledExactlyOnceWith(23, h.rows[23]);
    expect(h.getScopedParameter).toHaveBeenCalledWith(23);
    expect(h.state.activeRowIndex).toBe(23);
    expect(updateSelection).not.toHaveBeenCalled();
  });
  it.each([
    { disabled: true },
    { rowReadonly: true },
    { controlDisabled: true },
    { detailed: true },
    { displayOnly: true },
    { script: '' },
    { script: 'not valid javascript' },
    { script: '({ value: 1 })' },
  ])('does not execute or claim a blocked readonly cell: %j', (options) => {
    const h = harness(options);
    h.onFormClick(1, 0, new MouseEvent('click'));
    expect(h.open).not.toHaveBeenCalled();
    expect(h.getCellInteractionAttrs('directory', 1)).not.toHaveProperty('data-input-table-interactive');
  });
  it('passes the native event and current row data to the script', () => {
    const h = harness({ script: '({ data, rowIndex, rowData, onlineUtils }) => onlineUtils.open(data, rowIndex, rowData)' });
    const event = new MouseEvent('click');
    h.onFormClick(1, 0, event);
    expect(h.open).toHaveBeenCalledExactlyOnceWith(event, 1, h.rows[1]);
  });
  it('ignores removed rows', () => {
    const h = harness();
    h.onFormClick(25, 0, new MouseEvent('click'));
    expect(h.open).not.toHaveBeenCalled();
  });
});
