/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

import { faker } from '@faker-js/faker';
import {
  CollectionTriggerNode,
  ManualNode,
  apiCreateWorkflow,
  apiDeleteWorkflow,
  apiGetWorkflow,
  apiUpdateWorkflowTrigger,
  appendJsonCollectionName,
  generalWithNoRelationalFields,
  apiGetDataSourceCount,
} from '@nocobase/plugin-workflow-test/e2e';
import { expect, test } from '@nocobase/test/e2e';
import { dayjs } from '@nocobase/utils';

test('filter task node', async ({ page, mockPage, mockCollections, mockRecords }) => {
  //数据表后缀标识
  const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4);
  const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString();

  // 创建触发器节点数据表
  const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`;
  const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`;
  const triggerNodeFieldName = 'orgname';
  const triggerNodeFieldDisplayName = '公司名称(单行文本)';
  await mockCollections(
    appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText)
      .collections,
  );
  // 创建Manual节点数据表
  const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`;
  const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`;
  const manualNodeFieldName = 'orgname';
  const manualNodeFieldDisplayName = '公司名称(单行文本)';
  await mockCollections(
    appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText)
      .collections,
  );
  //添加工作流
  const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText;
  const workflowData = {
    current: true,
    options: { deleteExecutionOnStatus: [] },
    title: workFlowName,
    type: 'collection',
    enabled: true,
  };
  const workflow = await apiCreateWorkflow(workflowData);
  const workflowObj = JSON.parse(JSON.stringify(workflow));
  const workflowId = workflowObj.id;
  //配置工作流触发器
  const triggerNodeData = {
    config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 },
  };
  const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData);
  const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode));
  //配置Manual节点
  await page.goto(`admin/workflow/workflows/${workflowId}`);
  await page.waitForLoadState('networkidle');
  const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName);
  await collectionTriggerNode.addNodeButton.click();
  await page.getByRole('button', { name: 'manual', exact: true }).click();
  const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString();
  await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName);
  const manualNode = new ManualNode(page, manualNodeName);
  const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText();
  await manualNode.nodeConfigure.click();
  await manualNode.assigneesDropDown.click();
  await page.getByRole('option', { name: 'Super Admin' }).click();
  await manualNode.configureUserInterfaceButton.click();
  await manualNode.addBlockButton.hover();
  await manualNode.createRecordFormMenu.hover();
  const dataSourcesCount = await apiGetDataSourceCount();
  if (dataSourcesCount > 1) {
    await page.getByRole('menuitem', { name: 'Main right' }).hover();
  }
  await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click();
  await page.mouse.move(300, 0, { steps: 100 });
  await page
    .locator(`button[aria-label^="schema-initializer-Grid-form:configureFields-${manualNodeCollectionName}"]`)
    .hover();
  await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover();
  await page.getByRole('menuitem', { name: 'Edit block title' }).click();
  const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString();
  await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle);
  await page.getByRole('button', { name: 'OK', exact: true }).click();
  await page
    .locator(`button[aria-label^="schema-initializer-Grid-form:configureFields-${manualNodeCollectionName}"]`)
    .hover();
  await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click();
  await page.mouse.move(300, 0, { steps: 100 });
  await page.mouse.click(300, 0);
  await manualNode.submitButton.click();
  await page.waitForLoadState('networkidle');

  // 2、测试步骤：添加数据触发工作流
  const triggerNodeCollectionRecordOne = triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString();
  const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [
    { orgname: triggerNodeCollectionRecordOne },
  ]);
  await page.waitForTimeout(1000);
  // 3、预期结果：工作流成功触发,待办弹窗表单中显示数据
  const getWorkflow = await apiGetWorkflow(workflowId);
  const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow));
  const getWorkflowExecuted = getWorkflowObj.executed;
  expect(getWorkflowExecuted).toBe(1);

  const newPage = mockPage();
  await newPage.goto();
  await page.waitForLoadState('networkidle');
  await page.getByLabel('schema-initializer-Grid-page:addBlock').hover();
  await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click();
  await page.mouse.move(300, 0, { steps: 100 });
  await page.waitForTimeout(300);
  await page.getByLabel('action-Filter.Action-Filter-filter-users_jobs-workflow-todo').click();
  await page.getByText('Add condition', { exact: true }).click();
  await page.getByTestId('select-filter-field').click();
  await page.getByRole('menuitemcheckbox', { name: 'Task right' }).click();
  await page.getByRole('menuitemcheckbox', { name: 'Title' }).click();
  await page.getByRole('textbox').fill(manualNodeName);
  await page.getByRole('button', { name: 'Submit' }).click();

  // 3、预期结果：列表中出现筛选的工作流
  await expect(page.getByText(manualNodeName)).toBeAttached();

  // 4、后置处理：删除工作流
  await apiDeleteWorkflow(workflowId);
});

test('filter workflow name', async ({ page, mockPage, mockCollections, mockRecords }) => {
  //数据表后缀标识
  const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4);
  const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString();

  // 创建触发器节点数据表
  const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`;
  const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`;
  const triggerNodeFieldName = 'orgname';
  const triggerNodeFieldDisplayName = '公司名称(单行文本)';
  await mockCollections(
    appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText)
      .collections,
  );
  // 创建Manual节点数据表
  const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`;
  const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`;
  const manualNodeFieldName = 'orgname';
  const manualNodeFieldDisplayName = '公司名称(单行文本)';
  await mockCollections(
    appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText)
      .collections,
  );
  //添加工作流
  const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText;
  const workflowData = {
    current: true,
    options: { deleteExecutionOnStatus: [] },
    title: workFlowName,
    type: 'collection',
    enabled: true,
  };
  const workflow = await apiCreateWorkflow(workflowData);
  const workflowObj = JSON.parse(JSON.stringify(workflow));
  const workflowId = workflowObj.id;
  //配置工作流触发器
  const triggerNodeData = {
    config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 },
  };
  const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData);
  const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode));
  //配置Manual节点
  await page.goto(`admin/workflow/workflows/${workflowId}`);
  await page.waitForLoadState('networkidle');
  const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName);
  await collectionTriggerNode.addNodeButton.click();
  await page.getByRole('button', { name: 'manual', exact: true }).click();
  const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString();
  await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName);
  const manualNode = new ManualNode(page, manualNodeName);
  const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText();
  await manualNode.nodeConfigure.click();
  await manualNode.assigneesDropDown.click();
  await page.getByRole('option', { name: 'Super Admin' }).click();
  await manualNode.configureUserInterfaceButton.click();
  await manualNode.addBlockButton.hover();
  await manualNode.createRecordFormMenu.hover();
  const dataSourcesCount = await apiGetDataSourceCount();
  if (dataSourcesCount > 1) {
    await page.getByRole('menuitem', { name: 'Main right' }).hover();
  }
  await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click();
  await page.mouse.move(300, 0, { steps: 100 });
  await page
    .locator(`button[aria-label^="schema-initializer-Grid-form:configureFields-${manualNodeCollectionName}"]`)
    .hover();
  await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover();
  await page.getByRole('menuitem', { name: 'Edit block title' }).click();
  const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString();
  await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle);
  await page.getByRole('button', { name: 'OK', exact: true }).click();
  await page
    .locator(`button[aria-label^="schema-initializer-Grid-form:configureFields-${manualNodeCollectionName}"]`)
    .hover();
  await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click();
  await page.mouse.move(300, 0, { steps: 100 });
  await page.mouse.click(300, 0);
  await manualNode.submitButton.click();
  await page.waitForLoadState('networkidle');

  // 2、测试步骤：添加数据触发工作流
  const triggerNodeCollectionRecordOne = triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString();
  const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [
    { orgname: triggerNodeCollectionRecordOne },
  ]);
  await page.waitForTimeout(1000);
  // 3、预期结果：工作流成功触发,待办弹窗表单中显示数据
  const getWorkflow = await apiGetWorkflow(workflowId);
  const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow));
  const getWorkflowExecuted = getWorkflowObj.executed;
  expect(getWorkflowExecuted).toBe(1);

  const newPage = mockPage();
  await newPage.goto();
  await page.waitForLoadState('networkidle');
  await page.getByLabel('schema-initializer-Grid-page:addBlock').hover();
  await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click();
  await page.mouse.move(300, 0, { steps: 100 });
  await page.waitForTimeout(300);
  await page.getByLabel('action-Filter.Action-Filter-filter-users_jobs-workflow-todo').click();
  await page.getByText('Add condition', { exact: true }).click();
  await page.getByTestId('select-filter-field').click();
  await page.getByRole('menuitemcheckbox', { name: 'Workflow right' }).click();
  await page.getByRole('menuitemcheckbox', { name: 'Name' }).click();
  await page.getByRole('textbox').fill(workFlowName);
  await page.getByRole('button', { name: 'Submit' }).click();

  // 3、预期结果：列表中出现筛选的工作流
  await expect(page.getByText(manualNodeName)).toBeAttached();

  // 4、后置处理：删除工作流
  await apiDeleteWorkflow(workflowId);
});
