import { test, expect } from '@playwright/test';
import { adminPath, ensureDataSource, cleanupByNames } from './helpers.mjs';

const setJoditHtml = async (page, html) => {
  await page.evaluate((nextHtml) => {
    const host = /** @type {any} */ (document.getElementById('ms-template-jodit'));
    const instances = (window.Jodit && window.Jodit.instances) ? window.Jodit.instances : null;
    let jodit = host && host.jodit ? host.jodit : null;
    if (!jodit && instances) {
      jodit = instances['ms-template-jodit'] || instances.ms_template_jodit || null;
    }
    if (!jodit && instances && typeof instances === 'object') {
      const vals = Array.isArray(instances) ? instances : Object.values(instances);
      jodit = vals.find((x) => x && x.container && x.container.isConnected) || null;
    }
    if (!jodit) {
      throw new Error('Jodit instance not available');
    }
    if (typeof jodit.setEditorValue === 'function') {
      jodit.setEditorValue(nextHtml);
    } else {
      jodit.value = nextHtml;
    }
    if (typeof jodit.synchronizeValues === 'function') {
      jodit.synchronizeValues();
    }
  }, html);
};

const setJoditMode = async (page, modeName) => {
  await page.evaluate((nextModeName) => {
    const host = /** @type {any} */ (document.getElementById('ms-template-jodit'));
    const instances = (window.Jodit && window.Jodit.instances) ? window.Jodit.instances : null;
    let jodit = host && host.jodit ? host.jodit : null;
    if (!jodit && instances) {
      jodit = instances['ms-template-jodit'] || instances.ms_template_jodit || null;
    }
    if (!jodit && instances && typeof instances === 'object') {
      const vals = Array.isArray(instances) ? instances : Object.values(instances);
      jodit = vals.find((x) => x && x.container && x.container.isConnected) || null;
    }
    if (!jodit) {
      throw new Error('Jodit instance not available');
    }
    const modeValue = nextModeName === 'wysiwyg'
      ? window.Jodit.MODE_WYSIWYG
      : window.Jodit.MODE_SOURCE;
    if (typeof jodit.setMode !== 'function') {
      throw new Error('Jodit setMode is unavailable');
    }
    jodit.setMode(modeValue);
  }, modeName);
};

const ensureMailshotModalsClosed = async (page) => {
  const acceptDialog = async (dialog) => {
    await dialog.accept();
  };
  page.on('dialog', acceptDialog);
  try {
    const templateModal = page.locator('#ms-template-modal');
    if (await templateModal.isVisible().catch(() => false)) {
      await page.locator('#ms-template-close').click();
      await expect(templateModal).toBeHidden();
    }

    const editorModal = page.locator('#ms-editor-modal');
    if (await editorModal.isVisible().catch(() => false)) {
      await page.locator('#ms-close-editor').click();
      await expect(editorModal).toBeHidden();
    }
  } finally {
    page.off('dialog', acceptDialog);
  }
};

const openNewMailshotEditor = async (page) => {
  await ensureMailshotModalsClosed(page);
  await page.locator('#ms-open-new').click();
  await expect(page.locator('#ms-editor-modal')).toBeVisible();
};

test('mailshots editor: datasource-driven options + overlay editors + create', async ({ page, request }) => {
  const uniq = `${Date.now()}_${Math.floor(Math.random() * 100000)}`;
  const dsName = `e2e_ms_ds_${uniq}`;
  const purpose = `e2e_mailshot_${uniq}`;

  try {
    await ensureDataSource(request, dsName, 'contacts');

    await page.goto(adminPath('feca-mailshots-mailshots'));
    await expect(page.locator('h1', { hasText: 'Mailshots' })).toBeVisible();

    await openNewMailshotEditor(page);

    await page.locator('#ms_purpose').fill(purpose);
    await page.locator('#ms_ds').selectOption({ label: dsName });

    await expect.poll(async () => await page.locator('#ms-token-controls button, #ms-token-controls select option').count()).toBeGreaterThan(0);
    await expect.poll(async () => await page.locator('#ms_pdfname option').count()).toBeGreaterThan(1);
    await expect.poll(async () => await page.locator('#ms_email_field option').count()).toBeGreaterThan(1);

    const tokenChooser = page.locator('#ms-token-controls .feca-token-format-controls');
    await expect(tokenChooser).toBeVisible();
    await tokenChooser.locator('select').first().selectOption({ index: 1 });
    await tokenChooser.locator('select').nth(1).selectOption({ label: 'Long Date' });
    await tokenChooser.getByRole('button', { name: 'Insert' }).click();
    await expect(page.locator('#ms_subject')).toHaveValue(/\{\{ [^}]+ \| date\('l j F Y'\) \}\}/);

    await page.locator('#ms_subject').fill('Subject {{ contacts.id }}');

    await page.locator('#ms-edit-message').click();
    await expect(page.locator('#ms-template-modal')).toBeVisible();
    await expect(page.locator('.jodit-container')).toBeVisible();
    await setJoditHtml(page, '<style>.red-note{color:red;}</style><div class="red-note">Hello <strong>bold</strong> {{ contacts.id }}</div>');
    await page.locator('#ms-template-save').click();
    await expect(page.locator('#ms_message')).toHaveValue(/\.red-note\{color:red;\}/);
    await expect(page.locator('#ms_message')).toHaveValue(/class="red-note"/);
    await expect(page.locator('#ms_message')).toHaveValue(/<strong>bold<\/strong>/);

    await page.locator('#ms-edit-pdf').click();
    await expect(page.locator('#ms-template-modal')).toBeVisible();
    await setJoditHtml(page, '<p>PDF {{ contacts.id }}</p>');
    await page.locator('#ms-template-save').click();
    await expect(page.locator('#ms_pdfa')).toHaveValue(/<p>PDF \{\{ contacts\.id \}\}<\/p>/);

    await page.locator('#ms_email_field').evaluate((el) => {
      const select = /** @type {HTMLSelectElement} */ (el);
      const option = Array.from(select.options).find((o) => o.value && /email/i.test(o.value)) || Array.from(select.options).find((o) => o.value);
      if (option) {
        select.value = option.value;
        select.dispatchEvent(new Event('change', { bubbles: true }));
      }
    });

    await page.getByRole('button', { name: 'Save' }).first().click();
    await expect(page.getByRole('cell', { name: purpose })).toBeVisible();
  } finally {
    try {
      await cleanupByNames(request, { dataSourceNames: [dsName], mailshotPurposes: [purpose] });
    } catch {
      // best effort
    }
  }
});

test('mailshots editor: message save closes modal and persists on reopen', async ({ page }) => {
  const html = '<style>.red-note{color:red;}</style>\n<div class="red-note">Hello <strong>bold</strong> {{ contacts.id }}</div>';

  await page.goto(adminPath('feca-mailshots-mailshots'));
  await expect(page.locator('h1', { hasText: 'Mailshots' })).toBeVisible();

  await openNewMailshotEditor(page);

  await page.locator('#ms-edit-message').click();
  await expect(page.locator('#ms-template-modal')).toBeVisible();
  await setJoditHtml(page, html);

  await page.locator('#ms-template-save').click();
  await expect(page.locator('#ms-template-modal')).toBeHidden();
  await expect(page.locator('#ms_message')).toHaveValue(/<style>\.red-note\{color:red;\}<\/style>/);
  await expect(page.locator('#ms_message')).toHaveValue(/<div class="red-note">Hello <strong>bold<\/strong> {{ contacts\.id }}<\/div>/);
  await expect.poll(async () => {
    const text = (await page.locator('#ms-message-meta').innerText()).trim();
    const match = text.match(/^(\d+)\s+chars$/);
    return match ? Number(match[1]) : 0;
  }).toBeGreaterThan(0);

  await page.locator('#ms-edit-message').click();
  await expect(page.locator('#ms-template-modal')).toBeVisible();
  const reopened = await page.evaluate(() => {
    const host = /** @type {any} */ (document.getElementById('ms-template-jodit'));
    const instances = (window.Jodit && window.Jodit.instances) ? window.Jodit.instances : null;
    let jodit = host && host.jodit ? host.jodit : null;
    if (!jodit && instances) {
      jodit = instances['ms-template-jodit'] || instances.ms_template_jodit || null;
    }
    if (!jodit && instances && typeof instances === 'object') {
      const vals = Array.isArray(instances) ? instances : Object.values(instances);
      jodit = vals.find((x) => x && x.container && x.container.isConnected) || null;
    }
    if (!jodit) {
      throw new Error('Jodit instance not available');
    }
    if (typeof jodit.synchronizeValues === 'function') {
      jodit.synchronizeValues();
    }
    if (typeof jodit.getEditorValue === 'function') {
      return String(jodit.getEditorValue() || '');
    }
    return String(jodit.value || '');
  });
  expect(reopened).toContain('.red-note{color:red;}');
  expect(reopened).toContain('class="red-note"');
  expect(reopened).toContain('<strong>bold</strong>');
});

test('mailshots editor: save works in WYSIWYG mode with a single click', async ({ page }) => {
  await page.goto(adminPath('feca-mailshots-mailshots'));
  await expect(page.locator('h1', { hasText: 'Mailshots' })).toBeVisible();

  await openNewMailshotEditor(page);

  await page.locator('#ms-edit-message').click();
  await expect(page.locator('#ms-template-modal')).toBeVisible();
  await setJoditMode(page, 'wysiwyg');
  await setJoditHtml(page, '<p>WYSIWYG body {{ contacts_id }}</p>');
  await page.locator('#ms-template-save').click();

  await expect(page.locator('#ms-template-modal')).toBeHidden();
  await expect(page.locator('#ms_message')).toHaveValue(/WYSIWYG body/);
});

test('mailshots editor: allows save without recipient field and shows warning', async ({ page, request }) => {
  const uniq = `${Date.now()}_${Math.floor(Math.random() * 100000)}`;
  const dsName = `e2e_ms_ds_norec_${uniq}`;
  const purpose = `e2e_mailshot_norec_${uniq}`;

  try {
    await ensureDataSource(request, dsName, 'contacts');

    await page.goto(adminPath('feca-mailshots-mailshots'));
    await expect(page.locator('h1', { hasText: 'Mailshots' })).toBeVisible();

    await openNewMailshotEditor(page);
    await page.locator('#ms_purpose').fill(purpose);
    await page.locator('#ms_ds').selectOption({ label: dsName });
    await page.locator('#ms_subject').fill('No recipient email field');
    await page.locator('#ms-edit-message').click();
    await expect(page.locator('#ms-template-modal')).toBeVisible();
    await setJoditHtml(page, '<p>PDF-only workflow {{ contacts.id }}</p>');
    await page.locator('#ms-template-save').click();

    await expect(page.locator('#ms-recipient-warning')).toBeVisible();
    await expect(page.locator('#ms-recipient-warning')).toContainText('cannot be used to send a mailshot');

    await page.getByRole('button', { name: 'Save' }).first().click();
    await expect(page.getByRole('cell', { name: purpose })).toBeVisible();
  } finally {
    try {
      await cleanupByNames(request, { dataSourceNames: [dsName], mailshotPurposes: [purpose] });
    } catch {
      // best effort
    }
  }
});
