import { test, expect } from '@playwright/test';
import {
  loginAsAdmin,
  navigateToTransactions,
  waitForPageStable,
  waitForOffcanvasOpen,
  waitForOffcanvasClose,
  waitForSuccessSweetAlert,
  confirmSweetAlert,
  fillSelect2ById,
  setFlatpickrDate,
  getTodayDate,
  getPastDate,
  generateRandomAmount,
  generateUniqueReference,
  clickTableAction
} from './helpers/accountingcore';

/**
 * AccountingCore Transactions CRUD Tests
 *
 * Tests the Transactions management functionality including:
 * - Displaying transactions list with DataTable
 * - Creating income transactions
 * - Creating expense transactions with all fields
 * - Viewing transaction details in offcanvas
 * - Editing existing transactions
 * - Deleting transactions with confirmation
 * - Filtering and searching transactions
 */

test.describe('Transactions CRUD', () => {
  test.beforeEach(async ({ page }) => {
    await loginAsAdmin(page);
  });

  test('should display transactions list', async ({ page }) => {
    await test.step('Navigate to transactions', async () => {
      await navigateToTransactions(page);
    });

    await test.step('Verify DataTable is visible', async () => {
      await expect(page.locator('table').first()).toBeVisible();
      await expect(page.locator('.card').first()).toBeVisible();
    });

    await test.step('Verify Add Transaction button exists', async () => {
      const addButton = page.locator('button:has-text("Add"), button:has-text("New Transaction")').first();
      await expect(addButton).toBeVisible();
    });
  });

  test('should create income transaction', async ({ page }) => {
    await test.step('Navigate to transactions list', async () => {
      await navigateToTransactions(page);
      await waitForPageStable(page);
    });

    await test.step('Click Add Transaction button', async () => {
      const addButton = page.locator('button:has-text("Add"), button:has-text("New Transaction")').first();
      await addButton.click();
      await waitForOffcanvasOpen(page);
    });

    await test.step('Fill transaction form', async () => {
      await page.locator('#type').selectOption('income');
      await page.waitForTimeout(500);

      const amount = generateRandomAmount(500, 5000);
      await page.locator('#amount').fill(amount);

      // Select category using Select2
      const categorySelect2 = page.locator('#category_id + .select2-container, .select2-container').first();
      if (await categorySelect2.isVisible()) {
        await categorySelect2.click();
        await page.waitForTimeout(500);
        // Wait for dropdown and select first available option
        const firstOption = page.locator('.select2-results__option:not(.select2-results__message)').first();
        if (await firstOption.isVisible()) {
          await firstOption.click();
          await page.waitForTimeout(300);
        }
      }

      const transactionDate = getTodayDate();
      await setFlatpickrDate(page, '#transaction_date', transactionDate);

      await page.locator('#description').fill('Test income transaction from E2E test');
    });

    await test.step('Submit form', async () => {
      const submitButton = page.locator('.offcanvas.show button[type="submit"]').first();
      await submitButton.click();
      await waitForSuccessSweetAlert(page);
      await waitForOffcanvasClose(page);
    });

    await test.step('Verify table is visible', async () => {
      await expect(page.locator('table').first()).toBeVisible();
    });
  });

  test('should create expense transaction', async ({ page }) => {
    await test.step('Navigate to transactions list', async () => {
      await navigateToTransactions(page);
      await waitForPageStable(page);
    });

    await test.step('Click Add Transaction button', async () => {
      const addButton = page.locator('button:has-text("Add"), button:has-text("New Transaction")').first();
      await addButton.click();
      await waitForOffcanvasOpen(page);
    });

    await test.step('Fill expense form with all fields', async () => {
      await page.locator('#type').selectOption('expense');
      await page.waitForTimeout(500);

      const amount = generateRandomAmount(100, 2000);
      await page.locator('#amount').fill(amount);

      // Select category using Select2
      const categorySelect2 = page.locator('#category_id + .select2-container, .select2-container').first();
      if (await categorySelect2.isVisible()) {
        await categorySelect2.click();
        await page.waitForTimeout(500);
        // Wait for dropdown and select first available option
        const firstOption = page.locator('.select2-results__option:not(.select2-results__message)').first();
        if (await firstOption.isVisible()) {
          await firstOption.click();
          await page.waitForTimeout(300);
        }
      }

      const transactionDate = getPastDate(5);
      await setFlatpickrDate(page, '#transaction_date', transactionDate);

      await page.locator('#description').fill('Test expense transaction with all fields');

      const refNumber = generateUniqueReference();
      await page.locator('#reference_number').fill(refNumber);

      const paymentMethodSelect = page.locator('#payment_method');
      if (await paymentMethodSelect.isVisible()) {
        await paymentMethodSelect.selectOption('bank_transfer');
      }
    });

    await test.step('Submit form', async () => {
      const submitButton = page.locator('.offcanvas.show button[type="submit"]').first();
      await submitButton.click();
      await waitForSuccessSweetAlert(page);
      await waitForOffcanvasClose(page);
    });
  });

  test('should view transaction details', async ({ page }) => {
    await test.step('Navigate to transactions list', async () => {
      await navigateToTransactions(page);
      await waitForPageStable(page);
    });

    await test.step('Wait for DataTable to load', async () => {
      await page.waitForSelector('table tbody tr', { timeout: 10000 });
      await page.waitForTimeout(1000);
    });

    await test.step('Check if table has data', async () => {
      const rows = page.locator('table tbody tr:not(.child)');
      const rowCount = await rows.count();
      if (rowCount === 0) {
        test.skip();
        return;
      }
    });

    await test.step('Click View action', async () => {
      await clickTableAction(page, 0, 'View');
      await waitForOffcanvasOpen(page);
    });

    await test.step('Verify offcanvas shows details', async () => {
      await expect(page.locator('.offcanvas.show').first()).toBeVisible();
    });

    await test.step('Close offcanvas', async () => {
      // Press Escape to close - avoids demo banner intercepting button clicks
      await page.keyboard.press('Escape');
      await page.waitForTimeout(500);
      // Verify offcanvas closed
      try {
        await page.waitForSelector('.offcanvas.show', { state: 'hidden', timeout: 3000 });
      } catch {
        // If still visible, try pressing Escape again
        await page.keyboard.press('Escape');
        await page.waitForTimeout(500);
      }
    });
  });

  test('should edit transaction', async ({ page }) => {
    await test.step('Navigate to transactions list', async () => {
      await navigateToTransactions(page);
      await waitForPageStable(page);
    });

    await test.step('Wait for DataTable to load', async () => {
      await page.waitForSelector('table tbody tr', { timeout: 10000 });
      await page.waitForTimeout(1000);
    });

    await test.step('Check if table has data', async () => {
      const rows = page.locator('table tbody tr:not(.child)');
      const rowCount = await rows.count();
      if (rowCount === 0) {
        test.skip();
        return;
      }
    });

    await test.step('Click Edit action', async () => {
      await clickTableAction(page, 0, 'Edit');
      await waitForOffcanvasOpen(page);
    });

    await test.step('Modify transaction', async () => {
      const newAmount = generateRandomAmount(1000, 8000);
      await page.locator('.offcanvas.show #amount').first().fill(newAmount);
      await page.locator('.offcanvas.show #description').first().fill('Updated transaction via E2E test');
    });

    await test.step('Submit form', async () => {
      const submitButton = page.locator('.offcanvas.show button[type="submit"]').first();
      await submitButton.click();
      await waitForSuccessSweetAlert(page);
      await waitForOffcanvasClose(page);
    });
  });

  test('should delete transaction', async ({ page }) => {
    await test.step('Navigate to transactions list', async () => {
      await navigateToTransactions(page);
      await waitForPageStable(page);
    });

    await test.step('Wait for DataTable to load', async () => {
      await page.waitForSelector('table tbody tr', { timeout: 10000 });
      await page.waitForTimeout(1000);
    });

    await test.step('Check if table has data', async () => {
      const rows = page.locator('table tbody tr:not(.child)');
      const rowCount = await rows.count();
      if (rowCount === 0) {
        test.skip();
        return;
      }
    });

    await test.step('Click Delete action', async () => {
      await clickTableAction(page, 0, 'Delete');
    });

    await test.step('Confirm deletion', async () => {
      await confirmSweetAlert(page);
      await waitForSuccessSweetAlert(page);
    });
  });

  test('should search transactions', async ({ page }) => {
    await test.step('Navigate to transactions list', async () => {
      await navigateToTransactions(page);
      await waitForPageStable(page);
    });

    await test.step('Use DataTable search', async () => {
      const searchBox = page.locator('.dataTables_filter input[type="search"]').first();
      if (await searchBox.isVisible()) {
        await searchBox.fill('test');
        await page.waitForTimeout(1000);
        await expect(page.locator('table').first()).toBeVisible();
        await searchBox.fill('');
      }
    });
  });

  test('should validate required fields', async ({ page }) => {
    await test.step('Navigate to transactions list', async () => {
      await navigateToTransactions(page);
      await waitForPageStable(page);
    });

    await test.step('Click Add Transaction button', async () => {
      const addButton = page.locator('button:has-text("Add"), button:has-text("New Transaction")').first();
      await addButton.click();
      await waitForOffcanvasOpen(page);
    });

    await test.step('Try to submit empty form', async () => {
      const submitButton = page.locator('.offcanvas.show button[type="submit"]').first();
      await submitButton.click();
      await page.waitForTimeout(500);
    });

    await test.step('Verify form stays open', async () => {
      await expect(page.locator('.offcanvas.show').first()).toBeVisible();
    });
  });

  test('should cancel transaction creation', async ({ page }) => {
    await test.step('Navigate to transactions list', async () => {
      await navigateToTransactions(page);
      await waitForPageStable(page);
    });

    await test.step('Click Add Transaction button', async () => {
      const addButton = page.locator('button:has-text("Add"), button:has-text("New Transaction")').first();
      await addButton.click();
      await waitForOffcanvasOpen(page);
    });

    await test.step('Fill some data', async () => {
      await page.locator('#amount').fill('1000');
      await page.locator('#description').fill('Will be cancelled');
    });

    await test.step('Close offcanvas', async () => {
      // Press Escape to close - most reliable method
      await page.keyboard.press('Escape');
      await page.waitForTimeout(500);
    });

    await test.step('Verify back on list page', async () => {
      // Wait for offcanvas to close with longer timeout
      try {
        await page.waitForSelector('.offcanvas.show', { state: 'hidden', timeout: 3000 });
      } catch {
        // If still visible, try pressing Escape again
        await page.keyboard.press('Escape');
        await page.waitForTimeout(500);
      }
      await expect(page.locator('table').first()).toBeVisible();
    });
  });
});
