/**
 * Copyright (C) 2025 Brainformatik GmbH (info@brainformatik.com)
 *
 * This file is part of brainX.
 * All Rights Reserved.
 *
 * This part of brainX can not be copied and/or distributed without the
 * express permission of Brainformatik GmbH.
 */

export class ContactsListPage {
  constructor(page) {
    this.page = page;
  }

  async goto() {
    await this.page.goto('/contacts');
  }

  async waitForLoaded() {
    await this.page.locator('[data-swipe-entry]').first().waitFor({
      state: 'visible' 
    });
  }

  contactContainer(identifier = 0) {
    if (typeof identifier === 'string') {
      return this.page.locator(`[data-swipe-entry="${identifier}"]`);
    }
    return this.page.locator('[data-swipe-entry]').nth(identifier);
  }

  async contactIdByName(name) {
    const row = this.page.locator('[data-swipe-entry]').filter({
      hasText: name 
    }).first();
    await row.waitFor({
      state: 'visible' 
    });
    return row.getAttribute('data-swipe-entry');
  }

  async contactIdAt(index = 0) {
    const container = this.contactContainer(index);
    await container.waitFor({
      state: 'visible' 
    });
    return container.getAttribute('data-swipe-entry');
  }

  async openDetail(identifier) {
    const container = this.contactContainer(identifier);
    await container.waitFor({
      state: 'visible' 
    });
    const primaryAction = container
      .locator('[data-swipe-surface] button:not([data-swipe-action]), [data-swipe-surface] a:not([data-swipe-action])')
      .first();
    await primaryAction.waitFor({
      state: 'visible' 
    });
    await primaryAction.scrollIntoViewIfNeeded();
    await primaryAction.click();
  }

  async revealQuickActions(identifier) {
    const container = this.contactContainer(identifier);
    await container.waitFor({
      state: 'visible' 
    });
    await container.scrollIntoViewIfNeeded();
    const box = await container.boundingBox();
    if (!box) {
      throw new Error(`Unable to determine bounding box for contact ${identifier}`);
    }
    const startX = box.x + box.width - 5;
    const startY = box.y + box.height / 2;
    const endX = startX - box.width * 0.8;
    const endY = startY;
    try {
      await container.dispatchEvent('pointerdown', {
        pointerId: 1,
        pointerType: 'touch',
        clientX: startX,
        clientY: startY,
        button: 0,
        buttons: 1
      });
      await container.dispatchEvent('pointermove', {
        pointerId: 1,
        pointerType: 'touch',
        clientX: endX,
        clientY: endY,
        buttons: 1
      });
      await container.dispatchEvent('pointerup', {
        pointerId: 1,
        pointerType: 'touch',
        clientX: endX,
        clientY: endY,
        button: 0
      });
    } catch {
      await container.hover({
        position: {
          x: box.width - 5,
          y: box.height / 2 
        } 
      });
      await this.page.mouse.down();
      await this.page.mouse.move(endX, endY, {
        steps: 15 
      });
      await this.page.mouse.up();
    }
    await this.page.waitForTimeout(200);
  }

  async triggerQuickAction(identifier, actionId) {
    if (!actionId) {
      throw new Error('triggerQuickAction requires an action identifier');
    }
    await this.revealQuickActions(identifier);
    const button = this.contactContainer(identifier)
      .locator(`[data-test="quick-action"][data-action-id="${actionId}"]`)
      .first();
    await button.waitFor({
      state: 'attached' 
    });
    await button.waitFor({
      state: 'visible'
    });
    const enabled = await button.isEnabled();
    if (!enabled) {
      throw new Error(`Quick action "${actionId}" is disabled for ${identifier}`);
    }
    await button.evaluate((el) => {
      el.click();
    });
  }

  async openCallSheet(identifier) {
    await this.triggerQuickAction(identifier, 'call');
  }

  async tapEmail(identifier) {
    await this.triggerQuickAction(identifier, 'email');
  }

  bottomSheetOptions() {
    return this.page.locator('.phone-sheet__option, .email-sheet__option');
  }

  async chooseBottomSheetOption(optionText) {
    const option = this.bottomSheetOptions().filter({
      hasText: optionText 
    }).first();
    await option.waitFor({
      state: 'attached' 
    });
    await option.scrollIntoViewIfNeeded();
    await option.click();
  }
}
