import { expect, Locator } from '@playwright/test';
import { ProjectTypes, ViewTypes } from 'nocodb-sdk';
import { DashboardPage } from '..';
import BasePage from '../../Base';
import { DocsSidebarPage } from './DocsSidebar';
import { SidebarUserMenuObject } from './UserMenu';
import { SidebarProjectNodeObject } from './ProjectNode';
import { SidebarTableNodeObject } from './TableNode';
import { isEE } from '../../../setup/db';

export class SidebarPage extends BasePage {
  readonly dashboard: DashboardPage;
  readonly docsSidebar: DocsSidebarPage;
  readonly createProjectBtn: Locator;
  readonly userMenu: SidebarUserMenuObject;
  readonly baseNode: SidebarProjectNodeObject;
  readonly tableNode: SidebarTableNodeObject;

  constructor(dashboard: DashboardPage) {
    super(dashboard.rootPage);
    this.dashboard = dashboard;
    this.docsSidebar = new DocsSidebarPage(this);
    this.userMenu = new SidebarUserMenuObject(this);
    this.createProjectBtn = dashboard.get().getByTestId('nc-sidebar-create-base-btn');
    this.baseNode = new SidebarProjectNodeObject(this);
    this.tableNode = new SidebarTableNodeObject(this);
  }

  get() {
    return this.dashboard.get().locator('.nc-sidebar');
  }

  async isVisible() {
    return await this.get().isVisible();
  }

  async verifyVisibility({ isVisible }: { isVisible: boolean }) {
    if (isVisible) {
      await expect(this.get()).toBeVisible();
    } else {
      await expect(this.get()).not.toBeVisible();
    }
  }

  // async verifyQuickActions({ isVisible }: { isVisible: boolean }) {
  //   if (isVisible) await expect(this.get().getByTestId('nc-sidebar-search-btn')).toBeVisible();
  //   else await expect(this.get().getByTestId('nc-sidebar-search-btn')).toHaveCount(0);
  // }

  async verifyTeamAndSettings({ isVisible }: { isVisible: boolean }) {
    if (isVisible) await expect(this.get().getByTestId('nc-sidebar-team-settings-btn')).toBeVisible();
    else await expect(this.get().getByTestId('nc-sidebar-team-settings-btn')).toHaveCount(0);
  }

  async verifyCreateProjectBtn({ isVisible }: { isVisible: boolean }) {
    await this.dashboard.leftSidebar.verifyBaseListOpen(true);

    if (isVisible) await expect(this.createProjectBtn).toBeVisible();
    else await expect(this.createProjectBtn).toHaveCount(0);
  }

  async openProject({ title }: { title: string }) {
    await this.get().locator(`.base-title-node`).getByText(title).click();

    // TODO: Fix this
    await this.rootPage.waitForTimeout(1000);
  }

  async createProject({
    title,
    type,
    networkValidation = true,
    navigateTobase = true,
  }: {
    title: string;
    type: ProjectTypes;
    networkValidation?: boolean;
    navigateTobase?: boolean;
  }) {
    await this.dashboard.leftSidebar.verifyBaseListOpen(true);

    await this.createProjectBtn.click();
    if (type === ProjectTypes.DOCUMENTATION) {
      await this.dashboard.get().locator('.nc-create-base-btn-docs').click();
    }

    if (isEE()) {
      await this.rootPage.getByTestId('nc-base-create-menu').waitFor();
      await this.rootPage.getByTestId('nc-base-create-menu').getByTestId('nc-menu-from-scratch').click();
    }

    await this.dashboard.get().locator('.nc-metadb-base-name').clear();
    await this.dashboard.get().locator('.nc-metadb-base-name').fill(title);

    if (networkValidation) {
      await this.waitForResponse({
        uiAction: () => this.dashboard.get().getByTestId('docs-create-proj-dlg-create-btn').click(),
        httpMethodsToMatch: ['POST'],
        requestUrlPathToMatch: `/api/v1/db/meta/projects/`,
      });
    } else {
      await this.dashboard.get().getByTestId('docs-create-proj-dlg-create-btn').click();
    }

    if (type === ProjectTypes.DOCUMENTATION) {
      await this.dashboard.docs.pagesList.waitForOpen({ title });
    }

    // By default we navigate to base home page sidebar
    // If we want to show base list then wait for base homepage sidebar load and then try to show baselist sidebar
    if (!navigateTobase) {
      await this.dashboard.leftSidebar.active_base.waitFor({ state: 'visible' });
      await this.dashboard.leftSidebar.verifyBaseListOpen(true);
    }
  }

  async createView({ title, type }: { title: string; type: ViewTypes }) {
    const createViewButtonOfActiveProject = this.dashboard
      .get()
      .locator('.nc-table-node-wrapper[data-active="true"] .nc-create-view-btn');

    await createViewButtonOfActiveProject.waitFor({ state: 'visible' });
    await createViewButtonOfActiveProject.scrollIntoViewIfNeeded();
    await createViewButtonOfActiveProject.click();

    // TODO: Find a better way to do it
    let createViewTypeButton: Locator;

    if (type === ViewTypes.GRID) {
      createViewTypeButton = this.rootPage.getByTestId('sidebar-view-create-grid');
    } else if (type === ViewTypes.FORM) {
      createViewTypeButton = this.rootPage.getByTestId('sidebar-view-create-form');
    } else if (type === ViewTypes.KANBAN) {
      createViewTypeButton = this.rootPage.getByTestId('sidebar-view-create-kanban');
    } else if (type === ViewTypes.GALLERY) {
      createViewTypeButton = this.rootPage.getByTestId('sidebar-view-create-gallery');
    } else if (type === ViewTypes.CALENDAR) {
      createViewTypeButton = this.rootPage.getByTestId('sidebar-view-create-calendar');
    }

    await this.rootPage.waitForTimeout(750);
    const allButtons = await createViewTypeButton.all();
    for (const btn of allButtons) {
      if (await btn.isVisible()) {
        createViewTypeButton = btn;
        break;
      }
    }

    await createViewTypeButton.click({
      force: true,
    });

    await this.rootPage.locator('input[id="form_item_title"]:visible').waitFor({ state: 'visible' });
    await this.rootPage.locator('input[id="form_item_title"]:visible').fill(title);
    const submitAction = () =>
      this.rootPage.locator('.ant-modal-content').locator('button.ant-btn.ant-btn-primary').click();
    await this.waitForResponse({
      httpMethodsToMatch: ['POST'],
      requestUrlPathToMatch: 'ViewCreate',
      uiAction: submitAction,
      responseJsonMatcher: json => json.title === title,
    });
    // Todo: Wait for view to be rendered
    await this.rootPage.waitForTimeout(1000);
  }

  async verifyCreateViewButtonVisibility({ isVisible }: { isVisible: boolean }) {
    const createViewButtonOfActiveProject = this.dashboard
      .get()
      .locator('.nc-table-node-wrapper[data-active="true"] .nc-create-view-btn');

    if (isVisible) {
      await expect(createViewButtonOfActiveProject).toBeVisible();
    } else {
      await expect(createViewButtonOfActiveProject).toHaveCount(0);
    }
  }
}
