import { Page } from '@playwright/test';

/**
 * SystemCore Test Helper Functions
 *
 * Shared utilities for SystemCore module Playwright tests
 */

/**
 * Login as admin user
 */
export async function loginAsAdmin(page: Page) {
  await page.goto('/auth/login');
  await page.locator('#email').fill('admin@demo.com');
  await page.locator('#password').fill('password123');
  await page.locator('button[type="submit"]').click();
  await page.waitForURL('**/dashboard', { timeout: 15000 });
}

/**
 * Generate unique code with prefix
 */
export function generateUniqueCode(prefix: string = 'SC') {
  return prefix + Date.now().toString().slice(-6);
}

/**
 * Generate unique email address
 */
export function generateUniqueEmail() {
  return `test${Date.now()}@example.com`;
}

/**
 * Generate unique phone number
 */
export function generateUniquePhone() {
  return '+1555' + Date.now().toString().slice(-7);
}

/**
 * Generate unique name with prefix
 */
export function generateUniqueName(prefix: string = 'Test') {
  return `${prefix} ${Date.now().toString().slice(-4)}`;
}

/**
 * Fill a Select2 dropdown by searching and selecting
 */
export async function fillSelect2(page: Page, selector: string, searchText: string) {
  // Click the Select2 container to open dropdown
  const select2Container = page.locator(selector).locator('..').locator('.select2-selection');
  await select2Container.click();
  await page.waitForTimeout(300);

  // Type search text
  await page.keyboard.type(searchText);
  await page.waitForTimeout(500);

  // Wait for results and click first option
  await page.waitForSelector('.select2-results__option', { state: 'visible', timeout: 5000 });
  const firstOption = page.locator('.select2-results__option').first();
  await firstOption.click();
  await page.waitForTimeout(200);
}

/**
 * Fill Select2 using the sibling approach (for hidden select elements)
 */
export async function fillSelect2ById(page: Page, selectId: string, searchText: string) {
  // Click on the Select2 container that follows the hidden select
  await page.click(`#${selectId} + .select2-container, [aria-labelledby="select2-${selectId}-container"]`);
  await page.waitForTimeout(300);

  // Type in the search box
  const searchInput = page.locator('.select2-search__field');
  if (await searchInput.isVisible()) {
    await searchInput.fill(searchText);
  } else {
    await page.keyboard.type(searchText);
  }
  await page.waitForTimeout(500);

  // Wait for and click first result
  await page.waitForSelector('.select2-results__option:not(.select2-results__option--load-more)', { state: 'visible', timeout: 5000 });
  await page.click('.select2-results__option:first-child');
  await page.waitForTimeout(200);
}

/**
 * Set a Flatpickr date input value via JavaScript
 */
export async function setFlatpickrDate(page: Page, selector: string, date: string) {
  await page.evaluate(([sel, val]) => {
    const input = document.querySelector(sel) as HTMLInputElement;
    if (input) {
      // Try to use Flatpickr instance if available
      const fp = (input as any)._flatpickr;
      if (fp) {
        fp.setDate(val, true);
      } else {
        input.value = val;
        input.dispatchEvent(new Event('change', { bubbles: true }));
      }
    }
  }, [selector, date]);
  await page.waitForTimeout(200);
}

/**
 * Get today's date string (YYYY-MM-DD format)
 */
export function getTodayDate(): string {
  return new Date().toISOString().split('T')[0];
}

/**
 * Get future date string
 */
export function getFutureDate(daysAhead: number = 7): string {
  const date = new Date();
  date.setDate(date.getDate() + daysAhead);
  return date.toISOString().split('T')[0];
}

/**
 * Get past date string
 */
export function getPastDate(daysAgo: number = 30): string {
  const date = new Date();
  date.setDate(date.getDate() - daysAgo);
  return date.toISOString().split('T')[0];
}

/**
 * Confirm SweetAlert dialog
 */
export async function confirmSweetAlert(page: Page) {
  await page.waitForSelector('.swal2-popup', { state: 'visible', timeout: 5000 });
  await page.click('.swal2-confirm');
  await page.waitForTimeout(500);
}

/**
 * Cancel SweetAlert dialog
 */
export async function cancelSweetAlert(page: Page) {
  await page.waitForSelector('.swal2-popup', { state: 'visible', timeout: 5000 });
  await page.click('.swal2-cancel');
  await page.waitForTimeout(500);
}

/**
 * Wait for success SweetAlert and dismiss it
 */
export async function waitForSuccessSweetAlert(page: Page) {
  await page.waitForSelector('.swal2-popup.swal2-icon-success, .swal2-success', { state: 'visible', timeout: 10000 });
  // Click OK button if visible, otherwise wait for auto-dismiss
  const okButton = page.locator('.swal2-confirm');
  if (await okButton.isVisible()) {
    await okButton.click();
  }
  await page.waitForTimeout(500);
}

/**
 * Wait for DataTable to reload
 */
export async function waitForDataTableReload(page: Page, tableSelector: string) {
  await page.waitForLoadState('networkidle');
  await page.waitForTimeout(500);
  await page.waitForSelector(tableSelector, { timeout: 10000 });
}

/**
 * Wait for page to be fully loaded and stable
 */
export async function waitForPageStable(page: Page) {
  await page.waitForLoadState('networkidle');
  await page.waitForTimeout(500);
}

/**
 * Check if an element exists on the page
 */
export async function elementExists(page: Page, selector: string): Promise<boolean> {
  return await page.locator(selector).count() > 0;
}

/**
 * Close any open offcanvas
 */
export async function closeOffcanvas(page: Page) {
  // Find the currently open offcanvas
  const openOffcanvas = page.locator('.offcanvas.show').first();

  if (await openOffcanvas.isVisible()) {
    // Use Bootstrap's JavaScript API to close the offcanvas properly
    // This works even when demo banners or other elements block the close button
    await page.evaluate(() => {
      const offcanvasElement = document.querySelector('.offcanvas.show');
      if (offcanvasElement) {
        // Use Bootstrap's Offcanvas API to hide it
        const bsOffcanvas = (window as any).bootstrap?.Offcanvas?.getInstance(offcanvasElement);
        if (bsOffcanvas) {
          bsOffcanvas.hide();
        } else {
          // Fallback: manually remove the show class and backdrop
          offcanvasElement.classList.remove('show');
          const backdrop = document.querySelector('.offcanvas-backdrop');
          if (backdrop) {
            backdrop.remove();
          }
        }
      }
    });

    // Wait for the offcanvas to be fully closed
    await openOffcanvas.waitFor({ state: 'hidden', timeout: 5000 });
    await page.waitForTimeout(300);
  }
}

// ============================================
// Navigation Helpers
// ============================================

/**
 * Navigate to SystemCore dashboard
 */
export async function navigateToDashboard(page: Page) {
  await page.goto('/systemcore');
  await waitForPageStable(page);
}

/**
 * Navigate to Customers list page
 */
export async function navigateToCustomers(page: Page) {
  await page.goto('/systemcore/customers');
  await page.waitForSelector('#customersTable', { timeout: 10000 });
}

/**
 * Navigate to Customer create page
 */
export async function navigateToCustomerCreate(page: Page) {
  await page.goto('/systemcore/customers/create');
  await waitForPageStable(page);
}

/**
 * Navigate to Customer show page
 */
export async function navigateToCustomerShow(page: Page, customerId: number) {
  await page.goto(`/systemcore/customers/${customerId}`);
  await waitForPageStable(page);
}

/**
 * Navigate to Customer edit page
 */
export async function navigateToCustomerEdit(page: Page, customerId: number) {
  await page.goto(`/systemcore/customers/${customerId}/edit`);
  await waitForPageStable(page);
}

/**
 * Navigate to Suppliers list page
 */
export async function navigateToSuppliers(page: Page) {
  await page.goto('/systemcore/suppliers');
  await page.waitForSelector('#suppliersTable', { timeout: 10000 });
}

/**
 * Navigate to Supplier create page
 */
export async function navigateToSupplierCreate(page: Page) {
  await page.goto('/systemcore/suppliers/create');
  await waitForPageStable(page);
}

/**
 * Navigate to Supplier show page
 */
export async function navigateToSupplierShow(page: Page, supplierId: number) {
  await page.goto(`/systemcore/suppliers/${supplierId}`);
  await waitForPageStable(page);
}

/**
 * Navigate to Supplier edit page
 */
export async function navigateToSupplierEdit(page: Page, supplierId: number) {
  await page.goto(`/systemcore/suppliers/${supplierId}/edit`);
  await waitForPageStable(page);
}

/**
 * Navigate to Products list page
 */
export async function navigateToProducts(page: Page) {
  await page.goto('/systemcore/products');
  await page.waitForSelector('#productsTable', { timeout: 10000 });
}

/**
 * Navigate to Product create page
 */
export async function navigateToProductCreate(page: Page) {
  await page.goto('/systemcore/products/create');
  await waitForPageStable(page);
}

/**
 * Navigate to Product show page
 */
export async function navigateToProductShow(page: Page, productId: number) {
  await page.goto(`/systemcore/products/${productId}`);
  await waitForPageStable(page);
}

/**
 * Navigate to Product edit page
 */
export async function navigateToProductEdit(page: Page, productId: number) {
  await page.goto(`/systemcore/products/${productId}/edit`);
  await waitForPageStable(page);
}

/**
 * Navigate to Payment Terms list page
 */
export async function navigateToPaymentTerms(page: Page) {
  await page.goto('/systemcore/payment-terms');
  await page.waitForSelector('#paymentTermsTable, .card', { timeout: 10000 });
}

/**
 * Navigate to Payment Term create page
 */
export async function navigateToPaymentTermCreate(page: Page) {
  await page.goto('/systemcore/payment-terms/create');
  await waitForPageStable(page);
}

/**
 * Navigate to Tax Configurations list page
 */
export async function navigateToTaxConfigurations(page: Page) {
  await page.goto('/systemcore/tax-configurations');
  await page.waitForSelector('#taxConfigurationsTable, .card', { timeout: 10000 });
}

/**
 * Navigate to Tax Configuration create page
 */
export async function navigateToTaxConfigurationCreate(page: Page) {
  await page.goto('/systemcore/tax-configurations/create');
  await waitForPageStable(page);
}

/**
 * Navigate to Product Categories list page
 */
export async function navigateToProductCategories(page: Page) {
  await page.goto('/systemcore/product-categories');
  await page.waitForSelector('#productCategoriesTable, .card', { timeout: 10000 });
}

/**
 * Navigate to Product Category create page
 */
export async function navigateToProductCategoryCreate(page: Page) {
  await page.goto('/systemcore/product-categories/create');
  await waitForPageStable(page);
}

/**
 * Navigate to Sales Orders list page
 */
export async function navigateToSalesOrders(page: Page) {
  await page.goto('/systemcore/sales-orders');
  await page.waitForSelector('.card', { timeout: 10000 });
}

/**
 * Navigate to Sales Order create page
 */
export async function navigateToSalesOrderCreate(page: Page) {
  await page.goto('/systemcore/sales-orders/create');
  await waitForPageStable(page);
}

/**
 * Navigate to Sales Order show page
 */
export async function navigateToSalesOrderShow(page: Page, orderId: number) {
  await page.goto(`/systemcore/sales-orders/${orderId}`);
  await waitForPageStable(page);
}

/**
 * Navigate to Purchase Orders list page
 */
export async function navigateToPurchaseOrders(page: Page) {
  await page.goto('/systemcore/purchase-orders');
  await page.waitForSelector('.card', { timeout: 10000 });
}

/**
 * Navigate to Purchase Order create page
 */
export async function navigateToPurchaseOrderCreate(page: Page) {
  await page.goto('/systemcore/purchase-orders/create');
  await waitForPageStable(page);
}

/**
 * Navigate to Purchase Order show page
 */
export async function navigateToPurchaseOrderShow(page: Page, orderId: number) {
  await page.goto(`/systemcore/purchase-orders/${orderId}`);
  await waitForPageStable(page);
}

// ============================================
// Order Line Item Helpers
// ============================================

/**
 * Add a line item to an order form
 */
export async function addOrderLineItem(
  page: Page,
  productSearch: string,
  quantity: number = 1,
  unitPrice?: number
) {
  // Click add line item button
  await page.click('#addLineItem, .add-line-item, button:has-text("Add Line")');
  await page.waitForTimeout(300);

  // Find the last line item row
  const lastRow = page.locator('#lineItemsContainer tr, .line-items-container tr').last();

  // Fill product using Select2
  const productSelect = lastRow.locator('[name*="product_id"], [id*="product_id"]');
  const selectId = await productSelect.getAttribute('id');
  if (selectId) {
    await fillSelect2ById(page, selectId, productSearch);
  }

  // Fill quantity
  await lastRow.locator('[name*="quantity"]').fill(quantity.toString());

  // Fill unit price if provided
  if (unitPrice !== undefined) {
    await lastRow.locator('[name*="unit_price"]').fill(unitPrice.toString());
  }

  await page.waitForTimeout(200);
}

/**
 * Remove a line item from an order form by index (0-based)
 */
export async function removeOrderLineItem(page: Page, index: number = 0) {
  const rows = page.locator('#lineItemsContainer tr, .line-items-container tr');
  const row = rows.nth(index);
  await row.locator('.remove-line, .btn-remove, button:has-text("Remove")').click();
  await page.waitForTimeout(200);
}

/**
 * Get the count of line items in an order form
 */
export async function getLineItemCount(page: Page): Promise<number> {
  return await page.locator('#lineItemsContainer tr, .line-items-container tr').count();
}
