import { test, expect } from '@playwright/test';
import {
  loginAsAdmin,
  generateUniqueProjectName,
  generateUniqueCode,
  navigateToProjects,
  navigateToProjectCreate,
  fillProjectForm,
  confirmSweetAlert,
  waitForPageStable,
  waitForDataTable,
  searchInDataTable,
  getTodayDate,
  getFutureDateMonths,
  ProjectData
} from './helpers/pmcore';

/**
 * PM Core Projects CRUD Tests
 *
 * Tests the Project management functionality including:
 * - Viewing projects list page with DataTable
 * - Creating a project with required fields only
 * - Creating a project with all fields (Select2, Flatpickr)
 * - Validating required fields
 * - Viewing project details
 * - Editing an existing project
 * - Deleting a project with SweetAlert confirmation
 * - Searching projects in DataTable
 */

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

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

    await test.step('Verify page title', async () => {
      const pageTitle = page.locator('h4, h5').filter({ hasText: /project/i }).first();
      await expect(pageTitle).toBeVisible();
    });

    await test.step('Verify DataTable loads with correct columns', async () => {
      await waitForDataTable(page);

      const table = page.locator('table').first();
      await expect(table).toBeVisible();

      const nameHeader = table.locator('thead th').filter({ hasText: /name/i });
      await expect(nameHeader).toBeVisible();

      const statusHeader = table.locator('thead th').filter({ hasText: /status/i });
      await expect(statusHeader).toBeVisible();
    });

    await test.step('Verify Add Project button exists', async () => {
      const addButton = page.locator('a[href*="/projects/create"], button:has-text("Add")').first();
      await expect(addButton).toBeVisible();
    });
  });

  test('should create project with required fields', async ({ page }) => {
    const projectName = generateUniqueProjectName();

    await test.step('Navigate to project create page', async () => {
      await navigateToProjectCreate(page);
    });

    await test.step('Verify form is visible', async () => {
      await expect(page.locator('form:not(#logout-form-menu)').first()).toBeVisible();
      await expect(page.locator('#name')).toBeVisible();
    });

    await test.step('Fill required fields', async () => {
      const projectData: ProjectData = {
        name: projectName
      };

      await fillProjectForm(page, projectData);
    });

    await test.step('Submit form', async () => {
      await page.locator('button[type="submit"]').first().click();
      await page.waitForLoadState('networkidle');
    });

    await test.step('Verify redirect to projects list', async () => {
      await page.waitForURL(/\/projects/, { timeout: 15000 });
      await waitForPageStable(page);
    });

    await test.step('Verify project appears in list', async () => {
      await searchInDataTable(page, projectName);
      await page.waitForTimeout(1000);

      const projectRow = page.locator('table tbody tr').filter({ hasText: projectName });
      await expect(projectRow).toBeVisible();
    });
  });

  test('should create project with all fields', async ({ page }) => {
    const projectName = generateUniqueProjectName();
    const projectCode = generateUniqueCode('PRJ');
    const startDate = getTodayDate();
    const endDate = getFutureDateMonths(3);

    await test.step('Navigate to project create page', async () => {
      await navigateToProjectCreate(page);
    });

    await test.step('Fill all fields including Select2 and Flatpickr', async () => {
      const projectData: ProjectData = {
        name: projectName,
        code: projectCode,
        description: 'Comprehensive test project with all fields populated',
        startDate: startDate,
        endDate: endDate,
        budget: 50000,
        hourlyRate: 150,
        isBillable: true
      };

      await fillProjectForm(page, projectData);
    });

    await test.step('Submit form', async () => {
      await page.locator('button[type="submit"]').first().click();
      await page.waitForLoadState('networkidle');
    });

    await test.step('Verify redirect and project created', async () => {
      await page.waitForURL(/\/projects/, { timeout: 15000 });
      await waitForPageStable(page);

      await searchInDataTable(page, projectName);
      await page.waitForTimeout(1000);

      const projectRow = page.locator('table tbody tr').filter({ hasText: projectName });
      await expect(projectRow).toBeVisible();
    });
  });

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

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

    await test.step('Verify validation errors for required fields', async () => {
      const currentUrl = page.url();
      expect(currentUrl).toContain('/projects/create');

      const nameField = page.locator('#name');
      const isInvalid = await nameField.evaluate((el: HTMLInputElement) => {
        return !el.validity.valid || el.classList.contains('is-invalid');
      });
      expect(isInvalid).toBeTruthy();
    });
  });

  test('should view project details', async ({ page }) => {
    await test.step('Navigate to projects list', async () => {
      await navigateToProjects(page);
      await waitForDataTable(page);
    });

    await test.step('Open dropdown and click View', async () => {
      const rows = page.locator('table tbody tr:not(.child)');
      const rowCount = await rows.count();

      if (rowCount === 0) {
        test.skip();
        return;
      }

      const firstRow = rows.first();

      // Check if table is responsive (has expand control)
      const expandControl = firstRow.locator('.dtr-control, td.dtr-control').first();
      if (await expandControl.count() > 0 && await expandControl.isVisible()) {
        // Click to expand responsive row
        await expandControl.click();
        await page.waitForTimeout(300);
      }

      // Try to find dropdown toggle in main row or expanded child row
      let dropdownToggle = firstRow.locator('.dropdown-toggle, button.btn-icon').first();

      // If not visible in main row, check in child row (responsive expanded content)
      if (!await dropdownToggle.isVisible()) {
        const childRow = page.locator('table tbody tr.child').first();
        if (await childRow.count() > 0) {
          dropdownToggle = childRow.locator('.dropdown-toggle, button.btn-icon').first();
        }
      }

      // Click dropdown
      await dropdownToggle.click({ force: true });
      await page.waitForTimeout(300);

      // Click View option in dropdown
      const viewButton = page.locator('.dropdown-menu.show').locator('a:has-text("View"), .dropdown-item:has-text("View")').first();
      await viewButton.click();
    });

    await test.step('Verify detail page loads', async () => {
      await page.waitForURL(/\/projects\/\d+$/, { timeout: 10000 });
      await waitForPageStable(page);

      const detailCard = page.locator('.card').first();
      await expect(detailCard).toBeVisible();
    });
  });

  test('should edit project', async ({ page }) => {
    await test.step('Navigate to projects list', async () => {
      await navigateToProjects(page);
      await waitForDataTable(page);
    });

    await test.step('Navigate to edit page via actions dropdown', async () => {
      const rows = page.locator('table tbody tr:not(.child)');
      const rowCount = await rows.count();

      if (rowCount === 0) {
        test.skip();
        return;
      }

      const firstRow = rows.first();

      // Check if table is responsive (has expand control)
      const expandControl = firstRow.locator('.dtr-control, td.dtr-control').first();
      if (await expandControl.count() > 0 && await expandControl.isVisible()) {
        // Click to expand responsive row
        await expandControl.click();
        await page.waitForTimeout(300);
      }

      // Try to find dropdown toggle in main row or expanded child row
      let dropdownToggle = firstRow.locator('.dropdown-toggle, button.btn-icon').first();

      // If not visible in main row, check in child row (responsive expanded content)
      if (!await dropdownToggle.isVisible()) {
        const childRow = page.locator('table tbody tr.child').first();
        if (await childRow.count() > 0) {
          dropdownToggle = childRow.locator('.dropdown-toggle, button.btn-icon').first();
        }
      }

      // Click dropdown
      await dropdownToggle.click({ force: true });
      await page.waitForTimeout(300);

      const editButton = page.locator('.dropdown-menu.show').locator('a[href*="/edit"], .dropdown-item:has-text("Edit")').first();
      await editButton.click();
    });

    await test.step('Wait for edit page to load', async () => {
      await page.waitForURL(/\/projects\/\d+\/edit/, { timeout: 10000 });
      await waitForPageStable(page);
    });

    await test.step('Change project name', async () => {
      const updatedName = generateUniqueProjectName() + ' (Updated)';
      await page.locator('#name').fill(updatedName);
    });

    await test.step('Submit changes', async () => {
      await page.locator('button[type="submit"]').first().click();
      await page.waitForLoadState('networkidle');
    });

    await test.step('Verify changes saved', async () => {
      await page.waitForURL(/\/projects/, { timeout: 15000 });
      await waitForPageStable(page);
    });
  });

  test('should delete project', async ({ page }) => {
    await test.step('Create a project to delete', async () => {
      await navigateToProjectCreate(page);

      const projectData: ProjectData = {
        name: generateUniqueProjectName() + ' (To Delete)'
      };

      await fillProjectForm(page, projectData);
      await page.locator('button[type="submit"]').first().click();
      await page.waitForLoadState('networkidle');
      await page.waitForURL(/\/projects/, { timeout: 15000 });
    });

    await test.step('Navigate to projects list', async () => {
      await navigateToProjects(page);
      await waitForDataTable(page);
    });

    await test.step('Search for the project to delete', async () => {
      await searchInDataTable(page, '(To Delete)');
      await page.waitForTimeout(1000);
    });

    await test.step('Click delete action', async () => {
      const rows = page.locator('table tbody tr:not(.child)');
      const rowCount = await rows.count();

      if (rowCount === 0) {
        test.skip();
        return;
      }

      const firstRow = rows.first();

      // Check if table is responsive (has expand control)
      const expandControl = firstRow.locator('.dtr-control, td.dtr-control').first();
      if (await expandControl.count() > 0 && await expandControl.isVisible()) {
        await expandControl.click();
        await page.waitForTimeout(300);
      }

      // Try to find dropdown toggle in main row or expanded child row
      let dropdownToggle = firstRow.locator('.dropdown-toggle, button.btn-icon').first();

      // If not visible in main row, check in child row (responsive expanded content)
      if (!await dropdownToggle.isVisible()) {
        const childRow = page.locator('table tbody tr.child').first();
        if (await childRow.count() > 0) {
          dropdownToggle = childRow.locator('.dropdown-toggle, button.btn-icon').first();
        }
      }

      await dropdownToggle.click({ force: true });
      await page.waitForTimeout(300);

      const deleteButton = page.locator('.dropdown-menu.show').locator('.dropdown-item:has-text("Delete")').first();
      await deleteButton.click();
      await page.waitForTimeout(300);
    });

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

    await test.step('Verify removal from list', async () => {
      await waitForPageStable(page);
      await page.waitForTimeout(1000);
    });
  });

  test('should search projects in DataTable', async ({ page }) => {
    await test.step('Navigate to projects list', async () => {
      await navigateToProjects(page);
      await waitForDataTable(page);
    });

    await test.step('Search for a project', async () => {
      const searchBox = page.locator('.dataTables_filter input[type="search"]');
      await expect(searchBox).toBeVisible();

      await searchBox.fill('Test');
      await page.waitForTimeout(1000);
    });

    await test.step('Verify table updates with search results', async () => {
      const table = page.locator('table').first();
      await expect(table).toBeVisible();

      const tbody = table.locator('tbody');
      await expect(tbody).toBeVisible();
    });
  });
});
