import { test, expect } from '@playwright/test';
import {
  createFanoutConfig,
  deleteFanoutConfig,
  getFanoutConfigs,
} from '../helpers/api';
import {
  createCaptureServer,
  fanoutHeader,
  openFanoutSettings,
  startIntegrationDraft,
} from '../helpers/fanout';

test.describe('Apprise integration settings', () => {
  let createdAppriseId: string | null = null;
  let receiver: ReturnType<typeof createCaptureServer>;
  let appriseUrl: string;

  test.beforeAll(async () => {
    receiver = createCaptureServer((port) => `json://127.0.0.1:${port}`);
    appriseUrl = await receiver.listen();
  });

  test.afterAll(async () => {
    receiver.close();
  });

  test.afterEach(async () => {
    if (createdAppriseId) {
      try {
        await deleteFanoutConfig(createdAppriseId);
      } catch {
        console.warn('Failed to delete test apprise config');
      }
      createdAppriseId = null;
    }
  });

  test('create apprise via UI, configure URLs, save as enabled', async ({ page }) => {
    await openFanoutSettings(page);
    await expect(page.getByRole('status', { name: 'Radio OK' })).toBeVisible();

    await startIntegrationDraft(page, 'Apprise');

    // Should navigate to the detail/edit view with a numbered default name
    await expect(page.locator('#fanout-edit-name')).toHaveValue(/Apprise #\d+/);

    // Fill in notification URL
    const urlsTextarea = page.locator('#fanout-apprise-urls');
    await urlsTextarea.fill(appriseUrl);

    // Verify preserve identity checkbox is checked by default
    const preserveIdentity = page.getByText('Preserve identity on Discord');
    await expect(preserveIdentity).toBeVisible();

    // Verify include routing path checkbox is checked by default
    const includePath = page.getByText('Include routing path in notifications');
    await expect(includePath).toBeVisible();

    // Rename it
    const nameInput = page.locator('#fanout-edit-name');
    await nameInput.clear();
    await nameInput.fill('E2E Apprise');

    // Save as enabled
    await page.getByRole('button', { name: /Save as Enabled/i }).click();
    await expect(page.getByText('Integration saved and enabled')).toBeVisible();

    // Should be back on list view with our apprise config visible
    await expect(page.getByText('E2E Apprise')).toBeVisible();
    await expect(page.getByText(appriseUrl)).toBeVisible();

    // Clean up via API
    const configs = await getFanoutConfigs();
    const apprise = configs.find((c) => c.name === 'E2E Apprise');
    if (apprise) {
      createdAppriseId = apprise.id;
    }
  });

  test('create apprise via API, verify options persist after edit', async ({ page }) => {
    const apprise = await createFanoutConfig({
      type: 'apprise',
      name: 'API Apprise',
      config: {
        urls: `${appriseUrl}\nslack://token_a/token_b/token_c`,
        preserve_identity: false,
        include_path: false,
      },
      enabled: true,
    });
    createdAppriseId = apprise.id;

    await openFanoutSettings(page);
    await expect(page.getByRole('status', { name: 'Radio OK' })).toBeVisible();

    // Click Edit on our apprise config
    const row = fanoutHeader(page, 'API Apprise');
    await expect(row).toBeVisible();
    await row.getByRole('button', { name: 'Edit' }).click();

    // Verify the URLs textarea has our content
    const urlsTextarea = page.locator('#fanout-apprise-urls');
    await expect(urlsTextarea).toHaveValue(new RegExp(appriseUrl.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
    await expect(urlsTextarea).toHaveValue(/slack:\/\/token_a/);

    // Verify checkboxes reflect our config (both unchecked)
    const preserveCheckbox = page
      .getByText('Preserve identity on Discord')
      .locator('xpath=ancestor::label[1]')
      .locator('input[type="checkbox"]');
    await expect(preserveCheckbox).not.toBeChecked();

    const pathCheckbox = page
      .getByText('Include routing path in notifications')
      .locator('xpath=ancestor::label[1]')
      .locator('input[type="checkbox"]');
    await expect(pathCheckbox).not.toBeChecked();

    // Go back
    page.once('dialog', (dialog) => dialog.accept());
    await page.getByText('← Back to list').click();
    await expect(row).toBeVisible();
  });

  test('apprise shows scope selector', async ({ page }) => {
    const apprise = await createFanoutConfig({
      type: 'apprise',
      name: 'Scope Apprise',
      config: { urls: appriseUrl },
    });
    createdAppriseId = apprise.id;

    await openFanoutSettings(page);
    await expect(page.getByRole('status', { name: 'Radio OK' })).toBeVisible();

    const row = fanoutHeader(page, 'Scope Apprise');
    await expect(row).toBeVisible();
    await row.getByRole('button', { name: 'Edit' }).click();

    // Verify scope selector is present
    await expect(page.getByText('Message Scope')).toBeVisible();
    await expect(page.getByText('All messages')).toBeVisible();

    // Select "All except listed" mode
    await page.getByText('All except listed channels/contacts').click();

    // Should show channel and contact lists with exclude label
    await expect(page.getByText('Channels (exclude)')).toBeVisible();

    // Go back
    page.once('dialog', (dialog) => dialog.accept());
    await page.getByText('← Back to list').click();
    await expect(row).toBeVisible();
  });

  test('apprise disabled config shows disabled status and can be enabled via save button', async ({
    page,
  }) => {
    const apprise = await createFanoutConfig({
      type: 'apprise',
      name: 'Disabled Apprise',
      config: { urls: appriseUrl },
      enabled: false,
    });
    createdAppriseId = apprise.id;

    await openFanoutSettings(page);
    await expect(page.getByRole('status', { name: 'Radio OK' })).toBeVisible();

    // Should show "Disabled" status text
    const row = fanoutHeader(page, 'Disabled Apprise');
    await expect(row).toContainText('Disabled');

    // Edit it
    await expect(row).toBeVisible();
    await row.getByRole('button', { name: 'Edit' }).click();

    // Save as enabled
    await page.getByRole('button', { name: /Save as Enabled/i }).click();
    await expect(page.getByText('Integration saved and enabled')).toBeVisible();

    // Verify it's now enabled via API
    const configs = await getFanoutConfigs();
    const updated = configs.find((c) => c.id === apprise.id);
    expect(updated?.enabled).toBe(true);
  });

  test('delete apprise via UI', async ({ page }) => {
    const apprise = await createFanoutConfig({
      type: 'apprise',
      name: 'Delete Me Apprise',
      config: { urls: appriseUrl },
    });
    createdAppriseId = apprise.id;

    await openFanoutSettings(page);
    await expect(page.getByRole('status', { name: 'Radio OK' })).toBeVisible();

    const row = fanoutHeader(page, 'Delete Me Apprise');
    await expect(row).toBeVisible();
    await row.getByRole('button', { name: 'Edit' }).click();

    // Accept the confirmation dialog
    page.once('dialog', (dialog) => dialog.accept());

    await page.getByRole('button', { name: 'Delete' }).click();

    // Should be back on list, apprise gone
    await expect(row).not.toBeVisible();
    createdAppriseId = null;
  });
});
