import { test, expect } from '@playwright/test';
import {
  loginAsAdmin,
  navigateToCategories,
  waitForPageStable,
  waitForOffcanvasOpen,
  waitForOffcanvasClose,
  waitForSuccessSweetAlert,
  confirmSweetAlert,
  generateUniqueCategoryName,
  clickTableAction
} from './helpers/accountingcore';

/**
 * AccountingCore Categories CRUD Tests
 *
 * Tests the Categories management functionality including:
 * - Viewing categories list
 * - Creating income categories
 * - Creating expense categories with color
 * - Editing existing categories
 * - Deleting categories with confirmation
 * - Validating required fields
 */

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

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

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

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

  test('should create income category', async ({ page }) => {
    const categoryName = generateUniqueCategoryName();

    await test.step('Navigate to categories page', async () => {
      await navigateToCategories(page);
    });

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

    await test.step('Fill category form', async () => {
      await page.locator('#name').fill(categoryName);
      await page.locator('#type').selectOption('income');
    });

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

    await test.step('Verify category was created', async () => {
      await waitForOffcanvasClose(page);
      // Reload to ensure DataTable refreshes with new data
      await page.reload({ waitUntil: 'networkidle' });
      await page.waitForTimeout(1000);
      // Search for the created category
      const searchBox = page.locator('.dataTables_filter input[type="search"]').first();
      if (await searchBox.isVisible()) {
        await searchBox.fill(categoryName);
        await page.waitForTimeout(1000);
      }
      const categoryRow = page.locator('table tbody tr').filter({ hasText: categoryName });
      await expect(categoryRow.first()).toBeVisible({ timeout: 10000 });
    });
  });

  test('should create expense category', async ({ page }) => {
    const categoryName = generateUniqueCategoryName();

    await test.step('Navigate to categories page', async () => {
      await navigateToCategories(page);
    });

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

    await test.step('Fill category form with color', async () => {
      await page.locator('#name').fill(categoryName);
      await page.locator('#type').selectOption('expense');
      const colorField = page.locator('#color');
      if (await colorField.isVisible()) {
        // Color inputs need special handling - use evaluate to set value
        await page.evaluate(() => {
          const colorInput = document.querySelector('#color') as HTMLInputElement;
          if (colorInput) {
            colorInput.value = '#FF5733';
            colorInput.dispatchEvent(new Event('change', { bubbles: true }));
          }
        });
      }
    });

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

  test('should edit category', async ({ page }) => {
    await test.step('Navigate to categories page', async () => {
      await navigateToCategories(page);
    });

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

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

    await test.step('Modify category name', async () => {
      const updatedName = generateUniqueCategoryName();
      await page.locator('#name').fill(updatedName);
    });

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

  test('should verify edit action is available', async ({ page }) => {
    await test.step('Navigate to categories page', async () => {
      await navigateToCategories(page);
      await waitForPageStable(page);
    });

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

    await test.step('Click action dropdown on first row', async () => {
      const rows = page.locator('table tbody tr:not(.child)');
      const row = rows.first();
      const actionButton = row.locator('button').first();
      await actionButton.click();
      await page.waitForTimeout(300);
    });

    await test.step('Verify Edit action is visible in dropdown', async () => {
      const editLink = page.locator('a:has-text("Edit"), .dropdown-item:has-text("Edit")').first();
      await expect(editLink).toBeVisible();
      // Close dropdown by pressing Escape
      await page.keyboard.press('Escape');
    });
  });

  test('should validate required fields', async ({ page }) => {
    await test.step('Navigate to categories page', async () => {
      await navigateToCategories(page);
    });

    await test.step('Open create form', async () => {
      const addButton = page.locator('button:has-text("Add"), button:has-text("New Category")').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 (validation failed)', async () => {
      await expect(page.locator('.offcanvas.show')).toBeVisible();
    });
  });

  test('should close offcanvas on cancel', async ({ page }) => {
    await test.step('Navigate to categories page', async () => {
      await navigateToCategories(page);
    });

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

    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 offcanvas closed', 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();
    });
  });
});
