import { DataTableActionHandler } from '@/manager/modules/ui/data-table/components/DataTableActionHandler';
import { DataTableRowSelector } from '@/manager/modules/ui/data-table/components/DataTableRowSelector';
import { IDataTableSortOrder } from '@/manager/modules/ui/data-table/types/data-table-types';
import { SingleSelect } from '@/manager/shared/components/SingleSelect';
import { BaseComponent } from '@/shared/base/BaseComponent';
import { getCount, getAttribute } from '@/shared/utils/locator-utils';
import { Locator } from '@playwright/test';

export class DataTable extends BaseComponent {
  readonly main = this.host.locator('.ui-data-grid');
  readonly table = this.main.locator('[data-test-id=ui-data-grid-table]:not(.disabled):not(.loading):not(.fetching)');
  readonly tbody = this.table.getByTestId('ui-data-grid-table-with-data');
  readonly rowSelector = new DataTableRowSelector(this.table);
  readonly actionHandler = new DataTableActionHandler(this.table);
  readonly paginationSelect = new SingleSelect(this.main.getByTestId('items-per-page-select'));

  async sortBy(columnheaderId: string, sortOrder: IDataTableSortOrder): Promise<void> {
    const columnheaderButton = this.getColumnheaderButton(columnheaderId);

    while ((await this.getColumnheaderButtonSortOrder(columnheaderButton)) !== sortOrder) {
      await columnheaderButton.click();
    }
  }

  selectRowsPerPage(rowsPerPage: number): Promise<void> {
    return this.paginationSelect.select(rowsPerPage.toString());
  }

  clickRow(index: number): Promise<void> {
    const row = this.getRow(index);
    return row.click();
  }

  getNumberOfRows(): Promise<number> {
    const rows = this.getRows();
    return getCount(this.tbody, rows);
  }

  getRowColumn(index: number, columnId: string): Locator {
    const row = this.getRow(index);
    return row.getByTestId(this.getColumnTestId(columnId));
  }

  getColumn(columnId: string): Locator {
    const rows = this.getRows();
    return rows.getByTestId(this.getColumnTestId(columnId));
  }

  getRow(index: number): Locator {
    const rows = this.getRows();
    return rows.nth(index);
  }

  getRows(): Locator {
    return this.tbody.locator('tr');
  }

  waitForLoading(): Promise<void> {
    return this.main.click({ trial: true });
  }

  private async getColumnheaderButtonSortOrder(columnheaderButton: Locator): Promise<IDataTableSortOrder> {
    const current = await getAttribute(columnheaderButton, 'aria-sort');

    switch (current) {
      case 'ascending':
        return 'asc';
      case 'descending':
        return 'desc';
      default:
        return 'none';
    }
  }

  private getColumnheaderButton(columnheaderId: string): Locator {
    const columnheaderTestId = this.getColumnheaderTestId(columnheaderId);
    return this.main.getByTestId(columnheaderTestId).locator('button');
  }

  private getColumnheaderTestId(columnheaderId: string): string {
    return `ui-data-grid-header-${columnheaderId}`;
  }

  private getColumnTestId(columnId: string): string {
    return `ui-data-grid-cell-${columnId}`;
  }
}
