import { Page } from 'playwright';
import { AbstractLocator, AbstractWidget } from './AbstractWidget';
import { WidgetFindOptions } from './types';
import { expect } from '../fixtures';
import { widgetStep } from '../utils';

export type CollapsibleFindOptions = WidgetFindOptions & {
  label?: string;
  labelExact?: boolean;
};

export class CollapsibleWidget extends AbstractWidget {
  type = 'collapsible';

  private alertSelector = '[role="alert"]';

  constructor(
    protected findOptions: CollapsibleFindOptions,
    protected readonly page: Page,
    protected readonly parent?: AbstractWidget,
    protected readonly parentLocator?: AbstractLocator
  ) {
    super(findOptions, page, parent, parentLocator);
  }

  find() {
    let collapsible = this.makeLocator();
    const { label, labelExact } = this.findOptions;
    if (label) {
      collapsible = collapsible.filter({
        hasText: labelExact ? new RegExp(`^${label}$`) : label,
      });
    }
    return collapsible;
  }

  private getLabelSelector() {
    return this.l.locator('[data-role="collapsible-control"]');
  }

  @widgetStep
  async toggle() {
    await this.getLabelSelector().click();
    return this;
  }

  private alert(text: string, exact: boolean = false) {
    return expect(
      this.l
        .locator(this.alertSelector, {
          hasText: exact ? new RegExp(`^${text}$`) : text,
        })
        .first()
    );
  }

  @widgetStep
  async toHaveAlert(text: string, exact: boolean = false) {
    await this.alert(text, exact).toBeVisible();
  }

  @widgetStep
  async notToHaveAlert(text: string, exact: boolean = false) {
    await this.alert(text, exact).not.toBeVisible();
  }

  get content() {
    return this.l.locator('.collapse');
  }

  @widgetStep
  async toBeOpen() {
    return expect(this.content).toBeVisible();
  }

  @widgetStep
  async toBeClosed() {
    return expect(this.content).not.toBeVisible();
  }
}
