import type { Page } from "@playwright/test";
import { expect, test } from "../../fixtures";
import { adjustScreenView } from "../../utils/adjust-screen-view";
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
import { TEXTS } from "../../utils/constants/texts";
import { loadDotenvIfLocal } from "../../utils/env/load-dotenv";
import { skipIfMissing } from "../../utils/env/skip-if-missing";
import { lockFlow, unlockFlow } from "../../utils/lock-flow";
import { unselectNodes } from "../../utils/unselect-nodes";

test(
  "user must be able to lock a flow and it must be saved",
  { tag: ["@release", "@components"] },
  async ({ page }) => {
    skipIfMissing.openAiKey();
    loadDotenvIfLocal(__dirname);
    await awaitBootstrapTest(page);

    await page.getByTestId("side_nav_options_all-templates").click();
    await page
      .getByRole("heading", { name: TEXTS.templateBasicPrompting })
      .click();

    await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
      timeout: 100000,
      state: "visible",
    });
    await page.waitForTimeout(500);

    await lockFlow(page);

    await page.getByTestId("icon-ChevronLeft").click();
    await page.waitForSelector('[data-testid="mainpage_title"]', {
      timeout: 3000,
    });

    await page.getByTestId("list-card").first().click();
    await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
      timeout: 100000,
      state: "visible",
    });
    await page.waitForTimeout(500);

    //ensure the UI is updated

    await unlockFlow(page);

    await page.getByTestId("icon-ChevronLeft").click();
    await page.waitForSelector('[data-testid="mainpage_title"]', {
      timeout: 3000,
    });

    await page.getByTestId("list-card").first().click();

    await page.waitForSelector('[data-testid="canvas_controls_dropdown"]', {
      timeout: 100000,
      state: "visible",
    });
    await page.waitForTimeout(500);

    await tryDeleteEdge(page);
    await page.waitForTimeout(500);

    // Delete edges one by one (when unlocked, should work)
    await page.locator(".react-flow__edge").nth(0).click();
    await page.waitForTimeout(200);
    await page.keyboard.press("Backspace");
    await page.waitForTimeout(300);
    let numberOfEdges = await page.locator(".react-flow__edge").count();
    expect(numberOfEdges).toBe(2);

    await page.locator(".react-flow__edge").nth(0).click();
    await page.waitForTimeout(200);
    await page.keyboard.press("Backspace");
    await page.waitForTimeout(300);
    numberOfEdges = await page.locator(".react-flow__edge").count();
    expect(numberOfEdges).toBe(1);

    await page.locator(".react-flow__edge").nth(0).click();
    await page.waitForTimeout(200);
    await page.keyboard.press("Backspace");
    await page.waitForTimeout(300);
    numberOfEdges = await page.locator(".react-flow__edge").count();
    expect(numberOfEdges).toBe(0);

    await tryConnectNodes(page);

    await unselectNodes(page);

    await page.getByText(TEXTS.componentChatInput, { exact: true }).click();

    await adjustScreenView(page);

    await page.getByTestId("handle-prompt-shownode-prompt-right").click();
    await page
      .getByTestId("handle-languagemodelcomponent-shownode-system message-left")
      .click();

    await page
      .getByTestId("handle-chatinput-shownode-chat message-right")
      .click();
    await page
      .getByTestId("handle-languagemodelcomponent-shownode-input-left")
      .click();

    await page
      .getByTestId(
        "handle-languagemodelcomponent-shownode-model response-right",
      )
      .click();
    await page.getByTestId("handle-chatoutput-shownode-inputs-left").click();
    await page.waitForTimeout(300);
    numberOfEdges = await page.locator(".react-flow__edge").count();

    expect(numberOfEdges).toBe(3);
  },
);

async function tryConnectNodes(page: Page) {
  await lockFlow(page);

  const numberOfTries = 5;
  let numberOfEdges = await page.locator(".react-flow__edge").count();

  for (let i = 0; i < numberOfTries; i++) {
    try {
      await page.getByTestId("handle-prompt-shownode-prompt-right").click({
        timeout: 500,
      });
    } catch (_e) {
      numberOfEdges = await page.locator(".react-flow__edge").count();
      expect(numberOfEdges).toBe(0);
    }

    try {
      await page
        .getByTestId(
          "handle-languagemodelcomponent-shownode-system message-left",
        )
        .click({
          timeout: 500,
        });
    } catch (_e) {
      numberOfEdges = await page.locator(".react-flow__edge").count();
      expect(numberOfEdges).toBe(0);
    }
  }
  await unlockFlow(page);
}

async function tryDeleteEdge(page: Page) {
  await lockFlow(page);

  let numberOfEdges = await page.locator(".react-flow__edge").count();
  expect(numberOfEdges).toBe(3);
  const numberOfTries = 5;

  // When locked, clicking edges and pressing delete should not remove them
  for (let i = 0; i < numberOfTries; i++) {
    await page.locator(".react-flow__edge").nth(0).click();
    await page.waitForTimeout(200);
    await page.keyboard.press("Backspace");
    await page.waitForTimeout(200);

    numberOfEdges = await page.locator(".react-flow__edge").count();
    expect(numberOfEdges).toBe(3);
  }
  await unlockFlow(page);
}
