import { test, expect } from '@playwright/test';
import {
  loginAsAdmin,
  generateUniqueName,
  generateUniqueEmail,
  generateUniquePhone,
  navigateToLeads,
  waitForPageStable,
  waitForKanbanLoad,
  switchToKanbanView,
  switchToListView,
  confirmSweetAlert,
  waitForSuccessSweetAlert
} from '../helpers/crmcore';

/**
 * Leads CRUD Tests
 *
 * Tests the Lead management functionality including:
 * - Viewing leads list page (DataTable view)
 * - Switching between Kanban and List views
 * - Creating a lead via offcanvas form
 * - Viewing lead details
 * - Editing an existing lead
 * - Deleting a lead with confirmation
 * - Kanban board functionality
 * - Lead filtering by source/status
 */

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

  test('should display leads list page', async ({ page }) => {
    await navigateToLeads(page);

    // Verify page title
    await expect(page.locator('h4, h5').filter({ hasText: /leads/i }).first()).toBeVisible();

    // Verify view toggle buttons exist
    const kanbanBtn = page.locator('#btn-kanban-view, button[data-view="kanban"]').first();
    const listBtn = page.locator('#btn-list-view, button[data-view="list"]').first();

    await expect(kanbanBtn).toBeVisible();
    await expect(listBtn).toBeVisible();

    // Verify Add Lead button exists
    const addButton = page.locator('button:has-text("Add New Lead"), #add-new-lead-btn').first();
    await expect(addButton).toBeVisible();
  });

  test('should switch between Kanban and List views', async ({ page }) => {
    await navigateToLeads(page);
    await waitForPageStable(page);

    // Switch to Kanban view
    await switchToKanbanView(page);

    // Verify Kanban columns are visible
    await expect(page.locator('h5, h6').filter({ hasText: /pipeline|new|contacted/i }).first()).toBeVisible();

    // Switch back to List view
    await switchToListView(page);

    // Verify DataTable is visible
    await expect(page.locator('table, #leadsTable').first()).toBeVisible();
  });

  test('should display Kanban board with status columns', async ({ page }) => {
    await navigateToLeads(page);
    await waitForPageStable(page);

    // Switch to Kanban view
    await switchToKanbanView(page);
    await waitForKanbanLoad(page);

    // Verify column headers exist (New, Contacted, Qualified, etc.)
    const newColumn = page.locator('h6:has-text("New")').first();
    await expect(newColumn).toBeVisible();
  });

  test('should open lead creation form', async ({ page }) => {
    await navigateToLeads(page);
    await waitForPageStable(page);

    // Click Add New Lead button
    const addButton = page.locator('button:has-text("Add New Lead"), #add-new-lead-btn').first();
    await addButton.click();

    // Wait for offcanvas/dialog to open
    await page.waitForSelector('.offcanvas.show, dialog[open], #offcanvasLeadForm.show', { timeout: 5000 });

    // Verify form fields are visible
    await expect(page.locator('#title, input[name="title"]').first()).toBeVisible();
  });

  test('should create lead with required fields', async ({ page }) => {
    await navigateToLeads(page);
    await waitForPageStable(page);

    // Click Add New Lead button
    const addButton = page.locator('button:has-text("Add New Lead"), #add-new-lead-btn').first();
    await addButton.click();

    // Wait for form
    await page.waitForSelector('.offcanvas.show, dialog[open]', { timeout: 5000 });
    await page.waitForTimeout(500);

    // Fill required fields
    const leadTitle = generateUniqueName('Test Lead');
    await page.locator('#title, input[name="title"]').first().fill(leadTitle);

    // Submit form
    const saveButton = page.locator('button:has-text("Save Lead"), #saveLeadBtn').first();
    await saveButton.click();

    // Wait for response
    await page.waitForTimeout(2000);

    // Verify lead was created (either success message or lead appears in list)
    // Refresh and check
    await page.reload();
    await waitForPageStable(page);
  });

  test('should create lead with all fields', async ({ page }) => {
    await navigateToLeads(page);
    await waitForPageStable(page);

    // Click Add New Lead button
    const addButton = page.locator('button:has-text("Add New Lead"), #add-new-lead-btn').first();
    await addButton.click();

    // Wait for form
    await page.waitForSelector('.offcanvas.show, dialog[open]', { timeout: 5000 });
    await page.waitForTimeout(500);

    // Fill all fields
    const leadTitle = generateUniqueName('Complete Lead');
    const contactEmail = generateUniqueEmail();
    const contactPhone = generateUniquePhone();

    await page.locator('#title, input[name="title"]').first().fill(leadTitle);

    // Contact name
    const contactNameField = page.locator('#contact_name, input[name="contact_name"]').first();
    if (await contactNameField.isVisible()) {
      await contactNameField.fill('John Doe');
    }

    // Company name
    const companyNameField = page.locator('#company_name, input[name="company_name"]').first();
    if (await companyNameField.isVisible()) {
      await companyNameField.fill('Acme Corp');
    }

    // Contact email
    const emailField = page.locator('#contact_email, input[name="contact_email"]').first();
    if (await emailField.isVisible()) {
      await emailField.fill(contactEmail);
    }

    // Contact phone
    const phoneField = page.locator('#contact_phone, input[name="contact_phone"]').first();
    if (await phoneField.isVisible()) {
      await phoneField.fill(contactPhone);
    }

    // Value
    const valueField = page.locator('#value, #estimated_value, input[name="value"], input[name="estimated_value"]').first();
    if (await valueField.isVisible()) {
      await valueField.fill('50000');
    }

    // Select lead source if dropdown is visible
    const sourceSelect = page.locator('#lead_source_id, select[name="lead_source_id"]').first();
    if (await sourceSelect.isVisible()) {
      const options = await sourceSelect.locator('option').count();
      if (options > 1) {
        await sourceSelect.selectOption({ index: 1 });
      }
    }

    // Description
    const descField = page.locator('#description, textarea[name="description"]').first();
    if (await descField.isVisible()) {
      await descField.fill('Test lead with all fields filled');
    }

    // Submit form
    const saveButton = page.locator('button:has-text("Save Lead"), #saveLeadBtn').first();
    await saveButton.click();

    // Wait for response
    await page.waitForTimeout(2000);
  });

  test('should view lead details', async ({ page }) => {
    await navigateToLeads(page);
    await waitForPageStable(page);

    // Switch to list view for easier access
    await switchToListView(page);
    await page.waitForTimeout(500);

    // Wait for table to load
    const table = page.locator('table, #leadsTable').first();
    await expect(table).toBeVisible();

    const rows = page.locator('table tbody tr, #leadsTable tbody tr');
    const rowCount = await rows.count();

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

    // Find and click view action
    const firstRow = rows.first();
    const dropdownToggle = firstRow.locator('.dropdown-toggle, button.btn-icon').first();

    if (await dropdownToggle.isVisible()) {
      await dropdownToggle.click();
      await page.waitForTimeout(300);

      const viewButton = page.locator('.dropdown-item:has-text("View")').first();
      if (await viewButton.isVisible()) {
        await viewButton.click();
        await page.waitForURL(/\/leads\/\d+$/, { timeout: 10000 });
        await expect(page.locator('.card').first()).toBeVisible();
      }
    }
  });

  test('should edit existing lead', async ({ page }) => {
    await navigateToLeads(page);
    await waitForPageStable(page);

    // Switch to list view
    await switchToListView(page);
    await page.waitForTimeout(500);

    const rows = page.locator('table tbody tr, #leadsTable tbody tr');
    const rowCount = await rows.count();

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

    // Find and click edit action
    const firstRow = rows.first();
    const dropdownToggle = firstRow.locator('.dropdown-toggle, button.btn-icon').first();

    if (await dropdownToggle.isVisible()) {
      await dropdownToggle.click();
      await page.waitForTimeout(300);

      const editButton = page.locator('.dropdown-item:has-text("Edit")').first();
      if (await editButton.isVisible()) {
        await editButton.click();

        // Wait for edit form/page
        await page.waitForTimeout(1000);

        // If offcanvas form, modify title
        const titleField = page.locator('#title, input[name="title"]').first();
        if (await titleField.isVisible()) {
          const updatedTitle = generateUniqueName('Updated Lead');
          await titleField.fill(updatedTitle);

          // Save
          const saveButton = page.locator('button:has-text("Save"), button:has-text("Update")').first();
          await saveButton.click();
          await page.waitForTimeout(2000);
        }
      }
    }
  });

  test('should delete lead with confirmation', async ({ page }) => {
    await navigateToLeads(page);
    await waitForPageStable(page);

    // Switch to list view
    await switchToListView(page);
    await page.waitForTimeout(500);

    const rows = page.locator('table tbody tr, #leadsTable tbody tr');
    const rowCount = await rows.count();

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

    // Find and click delete action
    const firstRow = rows.first();
    const dropdownToggle = firstRow.locator('.dropdown-toggle, button.btn-icon').first();

    if (await dropdownToggle.isVisible()) {
      await dropdownToggle.click();
      await page.waitForTimeout(300);

      const deleteButton = page.locator('.dropdown-item:has-text("Delete"), .dropdown-item.text-danger').first();
      if (await deleteButton.isVisible()) {
        await deleteButton.click();

        // Confirm deletion
        await confirmSweetAlert(page);
        await page.waitForTimeout(1000);

        // Page should still be functional
        await expect(page.locator('.card').first()).toBeVisible();
      }
    }
  });

  test('should filter leads by source', async ({ page }) => {
    await navigateToLeads(page);
    await waitForPageStable(page);

    // Switch to list view
    await switchToListView(page);
    await page.waitForTimeout(500);

    // Find source filter dropdown
    const sourceFilter = page.locator('select:has(option:has-text("Select Source"))').first();

    if (await sourceFilter.isVisible()) {
      const options = await sourceFilter.locator('option').count();
      if (options > 1) {
        await sourceFilter.selectOption({ index: 1 });
        await page.waitForTimeout(1000);

        // Table should still be visible
        await expect(page.locator('table, #leadsTable').first()).toBeVisible();
      }
    }
  });

  test('should search leads in table', async ({ page }) => {
    await navigateToLeads(page);
    await waitForPageStable(page);

    // Switch to list view
    await switchToListView(page);
    await page.waitForTimeout(500);

    // Find search box
    const searchBox = page.locator('input[type="search"], .dataTables_filter input').first();

    if (await searchBox.isVisible()) {
      await searchBox.fill('test');
      await page.waitForTimeout(1000);

      // Table should still be visible
      await expect(page.locator('table, #leadsTable').first()).toBeVisible();
    }
  });

  test('should display lead card in Kanban view', async ({ page }) => {
    await navigateToLeads(page);
    await waitForPageStable(page);

    // Switch to Kanban view
    await switchToKanbanView(page);
    await waitForKanbanLoad(page);

    // Check if any lead cards exist
    const leadCards = page.locator('.kanban-item, .kanban-card, [class*="kanban"] .card');
    const cardCount = await leadCards.count();

    // Verify Kanban structure is present
    await expect(page.locator('.kanban-board, [class*="kanban"]').first()).toBeVisible();

    // If there are cards, verify they have expected structure
    if (cardCount > 0) {
      const firstCard = leadCards.first();
      await expect(firstCard).toBeVisible();
    }
  });
});
