import { test, expect } from '@playwright/test';
import {
  loginAsAdmin,
  generateUniqueName,
  generateUniqueEmail,
  generateUniquePhone,
  navigateToCustomers,
  navigateToCustomerShow,
  confirmSweetAlert,
  waitForPageStable,
  closeOffcanvas,
  waitForDataTableReload
} from '../helpers/systemcore';

/**
 * Customer Contacts Management Tests
 *
 * Tests the Customer Contacts functionality including:
 * - Viewing contacts section on customer show page
 * - Opening add contact offcanvas
 * - Creating contacts with required fields
 * - Setting contacts as primary
 * - Editing existing contacts
 * - Deleting contacts with confirmation
 */

test.describe('Customer Contacts', () => {
  let customerId: number;

  test.beforeEach(async ({ page }) => {
    // Login as admin
    await loginAsAdmin(page);

    // Navigate to customers list
    await navigateToCustomers(page);
    await waitForPageStable(page);

    // Wait for DataTable to load
    await waitForDataTableReload(page, '#customersTable');
    await page.waitForTimeout(1000);

    // Check if there are any customers in the table
    const rowCount = await page.locator('#customersTable tbody tr').count();
    const emptyTable = await page.locator('#customersTable tbody tr td.dataTables_empty').count();

    if (rowCount === 0 || emptyTable > 0) {
      // No customers available - tests will be skipped
      return;
    }

    // Get first customer ID from the table
    const firstRow = page.locator('#customersTable tbody tr').first();
    const viewButton = firstRow.locator('a[href*="/systemcore/customers/"]').first();

    // Check if view button exists
    if (await viewButton.count() === 0) {
      return;
    }

    const href = await viewButton.getAttribute('href', { timeout: 5000 });

    if (href) {
      const matches = href.match(/\/systemcore\/customers\/(\d+)/);
      if (matches && matches[1]) {
        customerId = parseInt(matches[1]);
      }
    }

    // Navigate to customer show page
    if (customerId) {
      await navigateToCustomerShow(page, customerId);
      await waitForPageStable(page);
    }
  });

  test('should display contacts section on customer show page', async ({ page }) => {
    // Skip if no customer available
    if (!customerId) {
      test.skip();
      return;
    }

    // Verify contacts card is visible - use more specific selector
    const contactsCard = page.locator('.card').filter({ hasText: 'Contacts' }).first();
    await expect(contactsCard).toBeVisible();

    // Verify Add button exists within the contacts card - use btn-sm to avoid ambiguity with "Add First Contact"
    const addButton = contactsCard.locator('button.btn-sm:has-text("Add"), button:has-text("Add First Contact")').first();
    await expect(addButton).toBeVisible();
  });

  test('should open add contact offcanvas', async ({ page }) => {
    // Skip if no customer available
    if (!customerId) {
      test.skip();
      return;
    }

    // Find the Add button in the contacts section - use btn-sm to avoid ambiguity with "Add First Contact"
    const contactsCard = page.locator('.card').filter({ hasText: 'Contacts' }).first();
    const addButton = contactsCard.locator('button.btn-sm:has-text("Add"), button:has-text("Add First Contact")').first();
    await addButton.click();
    await page.waitForTimeout(500);

    // Verify offcanvas opens
    const offcanvas = page.locator('#contactOffcanvas');
    await expect(offcanvas).toBeVisible();

    // Verify form fields are present
    await expect(page.locator('#contact_first_name')).toBeVisible();

    // Close offcanvas
    await closeOffcanvas(page);
  });

  test('should create contact with required fields', async ({ page }) => {
    // Skip if no customer available
    if (!customerId) {
      test.skip();
      return;
    }

    // Find the Add button in the contacts section - use btn-sm to avoid ambiguity with "Add First Contact"
    const contactsCard = page.locator('.card').filter({ hasText: 'Contacts' }).first();
    const addButton = contactsCard.locator('button.btn-sm:has-text("Add"), button:has-text("Add First Contact")').first();
    await addButton.click();
    await page.waitForTimeout(500);

    // Wait for offcanvas to open
    const offcanvas = page.locator('#contactOffcanvas');
    await expect(offcanvas).toBeVisible();

    // Fill contact form with required fields
    const firstName = generateUniqueName('John');
    const lastName = 'Doe';
    const email = generateUniqueEmail();

    // Select contact type (required by database)
    await page.locator('#contact_type').selectOption('primary');

    await page.locator('#contact_first_name').fill(firstName);
    await page.locator('#contact_last_name').fill(lastName);
    await page.locator('#contact_email').fill(email);
    await page.locator('#contact_phone').fill(generateUniquePhone());

    // Submit form and wait for navigation (AJAX success triggers page reload)
    await Promise.all([
      page.waitForEvent('load', { timeout: 20000 }),
      page.locator('#submitContactBtn').click()
    ]);

    // Wait for page to stabilize after reload
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    // After reload, verify contact appears in the list
    const updatedContactsCard = page.locator('.card').filter({ hasText: 'Contacts' }).first();
    await expect(updatedContactsCard).toContainText(firstName);
  });

  test('should edit existing contact', async ({ page }) => {
    // Skip if no customer available
    if (!customerId) {
      test.skip();
      return;
    }

    // First, check if there are any contacts
    const contactsCard = page.locator('.card').filter({ hasText: 'Contacts' }).first();
    const contactRows = contactsCard.locator('tbody tr');
    const contactCount = await contactRows.count();

    if (contactCount === 0) {
      // Create a contact first - use btn-sm to avoid ambiguity with "Add First Contact"
      const addButton = contactsCard.locator('button.btn-sm:has-text("Add"), button:has-text("Add First Contact")').first();
      await addButton.click();
      await page.waitForTimeout(500);

      const firstName = generateUniqueName('Test');
      // Select contact type (required by database)
      await page.locator('#contact_type').selectOption('primary');
      await page.locator('#contact_first_name').fill(firstName);
      await page.locator('#contact_last_name').fill('Contact');

      // Wait for page reload after creation
      await Promise.all([
        page.waitForEvent('load', { timeout: 20000 }),
        page.locator('#submitContactBtn').click()
      ]);
      await page.waitForLoadState('networkidle');
      await page.waitForTimeout(1000);
    }

    // Re-fetch the card after potential page reload
    const updatedContactsCard = page.locator('.card').filter({ hasText: 'Contacts' }).first();

    // Wait for contacts to be available
    await page.waitForSelector('.card:has-text("Contacts") tbody tr', { timeout: 10000 });

    // Find and click edit button - the dropdown is in the actions column
    const dropdownToggle = updatedContactsCard.locator('tbody tr').first().locator('.dropdown-toggle').first();
    await dropdownToggle.click();
    await page.waitForTimeout(300);

    // Use dropdown menu that's currently visible (has .show class)
    const editButton = page.locator('.dropdown-menu.show .dropdown-item:has-text("Edit")').first();
    await editButton.click();
    await page.waitForTimeout(500);

    // Wait for offcanvas to open
    const offcanvas = page.locator('#contactOffcanvas');
    await expect(offcanvas).toBeVisible();

    // Modify contact name
    const updatedName = generateUniqueName('Updated');
    await page.locator('#contact_first_name').clear();
    await page.locator('#contact_first_name').fill(updatedName);

    // Submit form and wait for page reload
    await Promise.all([
      page.waitForEvent('load', { timeout: 20000 }),
      page.locator('#submitContactBtn').click()
    ]);
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    // Verify changes appear - re-fetch the card after reload
    const finalContactsCard = page.locator('.card').filter({ hasText: 'Contacts' }).first();
    await expect(finalContactsCard).toContainText(updatedName);
  });

  test('should delete contact with confirmation', async ({ page }) => {
    // Skip if no customer available
    if (!customerId) {
      test.skip();
      return;
    }

    // First, ensure there's at least one contact
    const contactsCard = page.locator('.card').filter({ hasText: 'Contacts' }).first();
    const contactRows = contactsCard.locator('tbody tr');
    let contactCount = await contactRows.count();

    if (contactCount === 0) {
      // Create a contact first - use btn-sm to avoid ambiguity with "Add First Contact"
      const addButton = contactsCard.locator('button.btn-sm:has-text("Add"), button:has-text("Add First Contact")').first();
      await addButton.click();
      await page.waitForTimeout(500);

      // Select contact type (required by database)
      await page.locator('#contact_type').selectOption('primary');
      await page.locator('#contact_first_name').fill('Contact To Delete');
      await page.locator('#contact_last_name').fill('Test');

      // Wait for page reload after creation
      await Promise.all([
        page.waitForEvent('load', { timeout: 20000 }),
        page.locator('#submitContactBtn').click()
      ]);
      await page.waitForLoadState('networkidle');
      await page.waitForTimeout(1000);
    }

    // Re-fetch the card after potential page reload
    const updatedContactsCard = page.locator('.card').filter({ hasText: 'Contacts' }).first();

    // Wait for contacts to be available
    await page.waitForSelector('.card:has-text("Contacts") tbody tr', { timeout: 10000 });

    // Find and click delete button
    const dropdownToggle = updatedContactsCard.locator('tbody tr').first().locator('.dropdown-toggle').first();
    await dropdownToggle.click();
    await page.waitForTimeout(300);

    // Use dropdown menu that's currently visible (has .show class)
    const deleteButton = page.locator('.dropdown-menu.show .dropdown-item.text-danger:has-text("Delete")').first();
    await deleteButton.click();

    // Confirm SweetAlert dialog
    await confirmSweetAlert(page);

    // Wait for deletion to complete and page reload
    await page.waitForTimeout(2000);
  });

  test('should cancel contact creation and close offcanvas', async ({ page }) => {
    // Skip if no customer available
    if (!customerId) {
      test.skip();
      return;
    }

    // Find the Add button in the contacts section - use btn-sm to avoid ambiguity with "Add First Contact"
    const contactsCard = page.locator('.card').filter({ hasText: 'Contacts' }).first();
    const addButton = contactsCard.locator('button.btn-sm:has-text("Add"), button:has-text("Add First Contact")').first();
    await addButton.click();
    await page.waitForTimeout(500);

    // Wait for offcanvas to open
    const offcanvas = page.locator('#contactOffcanvas');
    await expect(offcanvas).toBeVisible();

    // Fill some data
    await page.locator('#contact_first_name').fill('Will be cancelled');

    // Click cancel button - use more specific selector within the offcanvas
    const cancelButton = offcanvas.locator('button.btn-label-secondary:has-text("Cancel")').first();
    await cancelButton.click();

    // Wait for Bootstrap offcanvas hide animation to complete
    await page.waitForTimeout(500);

    // Verify offcanvas is closed
    await expect(offcanvas).not.toBeVisible({ timeout: 5000 });
  });
});
