/**
 * 编辑订单 E2E 测试
 *
 * 测试范围：
 * - 编辑订单基本信息（名称、预计开始日期）
 * - 编辑订单关联信息（平台、公司、渠道）
 * - 编辑后列表更新验证
 * - 对话框交互验证
 * - 错误场景测试
 *
 * @packageDocumentation
 */

import { TIMEOUTS } from '../../utils/timeouts';
import { test, expect, Page } from '../../utils/test-setup';
import { selectRadixOption } from '@d8d/e2e-test-utils';

/**
 * 辅助函数：在创建订单对话框中选择残疾人
 *
 * @param page - Playwright Page 对象
 * @returns 是否成功选择了残疾人
 */
async function selectDisabledPersonForOrder(page: Page): Promise<boolean> {
  const selectPersonButton = page.getByRole('button', { name: '选择残疾人' });
  await selectPersonButton.click();

  await page.waitForSelector('[role="dialog"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });

  let hasData = false;
  try {
    const firstCheckbox = page.locator('table tbody tr').first().locator('input[type="checkbox"]').first();
    await firstCheckbox.waitFor({ state: 'visible', timeout: TIMEOUTS.ELEMENT_VISIBLE_SHORT });
    await firstCheckbox.check();
    console.debug('✓ 已选择第一个残疾人');
    hasData = true;
  } catch (error) {
    console.debug('没有可用的残疾人数据');
    hasData = false;
  }

  if (hasData) {
    const confirmButton = page.getByRole('button', { name: /^(确定|确认|选择)$/ });
    await confirmButton.click().catch(() => {
      console.debug('没有找到确认按钮，尝试关闭对话框');
      page.keyboard.press('Escape');
    });
  } else {
    await page.keyboard.press('Escape').catch(() => {
      console.debug('无法关闭对话框，可能已经自动关闭');
    });
  }

  await page.waitForTimeout(TIMEOUTS.MEDIUM);
  return hasData;
}

/**
 * 辅助函数：尝试更改 Radix Select 的值
 *
 * 用于测试平台、公司、渠道等下拉框的更换功能
 *
 * @param page - Playwright Page 对象
 * @param dataTestId - 下拉框的 data-testid 属性值
 * @param label - 下拉框的标签（用于 selectRadixOption）
 * @returns 是否成功更改了值
 */
async function tryChangeSelectValue(
  page: Page,
  dataTestId: string,
  label: string
): Promise<{ changed: boolean; newValue?: string }> {
  try {
    // 点击下拉框
    const trigger = page.locator(`[data-testid="${dataTestId}"]`);
    const count = await trigger.count();

    if (count === 0) {
      console.debug(`${label}选择器未找到`);
      return { changed: false };
    }

    // 获取当前值（通过触发器的文本内容）
    const currentValue = await trigger.textContent() || '';

    // 打开下拉框
    await trigger.click({ force: true });

    // 等待选项出现
    await page.waitForTimeout(TIMEOUTS.SHORT);

    // 获取所有可用选项
    const options = page.getByRole('option');
    const optionCount = await options.count();

    if (optionCount <= 1) {
      console.debug(`只有一个${label}选项，无法测试更换`);
      await page.keyboard.press('Escape'); // 关闭下拉框
      return { changed: false };
    }

    // 获取所有选项的文本
    const availableValues: string[] = [];
    for (let i = 0; i < optionCount; i++) {
      const text = await options.nth(i).textContent();
      if (text) availableValues.push(text);
    }

    // 选择与当前值不同的选项
    const newValue = availableValues.find(v => v !== currentValue && v.trim() !== '') ?? availableValues[1];

    if (newValue && newValue !== currentValue) {
      // 使用 selectRadixOption 工具进行选择
      await selectRadixOption(page, label, newValue);
      console.debug(`✓ 已选择不同的${label}: ${newValue}`);

      // 验证选择器确实更新到了新值
      const updatedValue = await trigger.textContent();
      if (updatedValue?.includes(newValue)) {
        return { changed: true, newValue };
      }
    }

    // 关闭下拉框
    await page.keyboard.press('Escape');
    return { changed: false };
  } catch (error) {
    console.debug(`${label}选择失败:`, error);
    return { changed: false };
  }
}

/**
 * 辅助函数：创建测试订单
 *
 * @param page - Playwright Page 对象
 * @param orderName - 订单名称
 * @returns 是否成功创建
 */
async function createTestOrder(page: Page, orderName: string): Promise<boolean> {
  // 打开创建对话框
  const addOrderButton = page.getByTestId('create-order-button');
  await addOrderButton.click();
  await page.waitForSelector('[role="dialog"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });

  // 填写必填字段
  await page.getByLabel(/订单名称|名称/).fill(orderName);
  await page.getByLabel(/预计开始日期|开始日期/).fill('2025-01-15');

  // 选择残疾人（必填）
  const hasDisabledPerson = await selectDisabledPersonForOrder(page);

  if (!hasDisabledPerson) {
    await page.keyboard.press('Escape');
    return false;
  }

  // 提交表单
  const submitButton = page.getByRole('button', { name: /^(创建|更新|保存)$/ });
  await submitButton.click();

  // 等待网络请求完成
  try {
    await page.waitForLoadState('networkidle', { timeout: TIMEOUTS.DIALOG });
  } catch {
    console.debug('networkidle 超时，继续检查 Toast 消息');
  }

  await page.waitForTimeout(TIMEOUTS.VERY_LONG);

  // 检查成功消息
  const successToast = page.locator('[data-sonner-toast][data-type="success"]');
  const hasSuccess = await successToast.count() > 0;

  // 等待对话框关闭
  const dialog = page.locator('[role="dialog"]');
  await dialog.waitFor({ state: 'hidden', timeout: TIMEOUTS.DIALOG }).catch(() => {
    console.debug('对话框关闭超时，可能已经关闭');
  });

  return hasSuccess;
}

/**
 * 辅助函数：获取订单列表中的预计开始日期
 *
 * @param page - Playwright Page 对象
 * @param orderName - 订单名称
 * @returns 预计开始日期字符串
 */
async function getOrderExpectedStartDate(page: Page, orderName: string): Promise<string | null> {
  const orderRow = page.locator('table tbody tr').filter({ hasText: orderName });

  // 查找包含日期的单元格（通常是第3或第4列）
  const cells = orderRow.locator('td');
  const cellCount = await cells.count();

  // 遍历单元格查找日期格式的文本
  for (let i = 0; i < cellCount; i++) {
    const text = await cells.nth(i).textContent();
    if (text && /^\d{4}-\d{2}-\d{2}$/.test(text.trim())) {
      return text.trim();
    }
  }

  return null;
}

test.describe.serial('编辑订单测试', () => {
  let testOrderName: string;

  test.beforeEach(async ({ adminLoginPage, orderManagementPage, testUsers }) => {
    // 以管理员身份登录后台
    await adminLoginPage.goto();
    await adminLoginPage.login(testUsers.admin.username, testUsers.admin.password);
    await adminLoginPage.expectLoginSuccess();
    await orderManagementPage.goto();

    // 创建测试订单
    const timestamp = Date.now();
    testOrderName = `编辑测试_${timestamp}`;

    const created = await createTestOrder(orderManagementPage.page, testOrderName);

    if (!created) {
      // 没有残疾人数据时，跳过测试
      test.skip(true, '没有残疾人数据，无法创建测试订单');
    }

    // 验证订单出现在列表中
    await expect(async () => {
      const exists = await orderManagementPage.orderExists(testOrderName);
      expect(exists).toBe(true);
    }).toPass({ timeout: TIMEOUTS.DIALOG });
  });

  test.afterEach(async ({ orderManagementPage }) => {
    // 清理测试数据
    try {
      const exists = await orderManagementPage.orderExists(testOrderName);
      if (exists) {
        await orderManagementPage.deleteOrder(testOrderName);
        console.debug(`✓ 已清理测试订单: ${testOrderName}`);
      }
    } catch (error) {
      console.debug(`清理测试订单失败:`, error);
    }
  });

  test.describe('编辑订单基本信息', () => {
    test('应该能修改订单名称', async ({ orderManagementPage }) => {
      const timestamp = Date.now();
      const newName = `${testOrderName}_修改${timestamp}`;
      const result = await orderManagementPage.editOrder(testOrderName, {
        name: newName,
      });

      expect(result.hasSuccess).toBe(true);
      expect(result.hasError).toBe(false);

      await expect(async () => {
        const exists = await orderManagementPage.orderExists(newName);
        expect(exists).toBe(true);
      }).toPass({ timeout: TIMEOUTS.DIALOG });

      // 更新测试订单名称供后续清理使用
      testOrderName = newName;
    });

    test('应该能修改预计开始日期', async ({ orderManagementPage }) => {
      const newDate = '2025-02-20';
      const result = await orderManagementPage.editOrder(testOrderName, {
        expectedStartDate: newDate,
      });

      expect(result.hasSuccess).toBe(true);
      expect(result.hasError).toBe(false);

      // 验证列表中日期确实更新了
      await expect(async () => {
        const actualDate = await getOrderExpectedStartDate(orderManagementPage.page, testOrderName);
        expect(actualDate).toBe(newDate);
      }).toPass({ timeout: TIMEOUTS.DIALOG });
    });

    test('应该能同时修改多个基本信息', async ({ orderManagementPage }) => {
      const timestamp = Date.now();
      const newName = `${testOrderName}_批量${timestamp}`;
      const newDate = '2025-03-15';
      const result = await orderManagementPage.editOrder(testOrderName, {
        name: newName,
        expectedStartDate: newDate,
      });

      expect(result.hasSuccess).toBe(true);
      expect(result.hasError).toBe(false);

      await expect(async () => {
        const exists = await orderManagementPage.orderExists(newName);
        expect(exists).toBe(true);
      }).toPass({ timeout: TIMEOUTS.DIALOG });

      // 验证日期也更新了
      const actualDate = await getOrderExpectedStartDate(orderManagementPage.page, newName);
      expect(actualDate).toBe(newDate);

      testOrderName = newName;
    });
  });

  test.describe('编辑订单关联信息', () => {
    test('应该能更换平台', async ({ orderManagementPage, page }) => {
      await orderManagementPage.openEditDialog(testOrderName);

      const result = await tryChangeSelectValue(page, 'platform-search-select', '平台');

      if (!result.changed) {
        await orderManagementPage.cancelDialog();
        test.skip(true, '无法更换平台（可能只有一个选项）');
        return;
      }

      // 提交表单
      const submitResult = await orderManagementPage.submitForm();
      expect(submitResult.hasSuccess).toBe(true);
      expect(submitResult.hasError).toBe(false);

      await orderManagementPage.waitForDialogClosed();

      const exists = await orderManagementPage.orderExists(testOrderName);
      expect(exists).toBe(true);
    });

    test('应该能更换公司', async ({ orderManagementPage, page }) => {
      await orderManagementPage.openEditDialog(testOrderName);

      const result = await tryChangeSelectValue(page, 'company-search-select', '公司');

      if (!result.changed) {
        await orderManagementPage.cancelDialog();
        test.skip(true, '无法更换公司（可能只有一个选项）');
        return;
      }

      const submitResult = await orderManagementPage.submitForm();
      expect(submitResult.hasSuccess).toBe(true);
      expect(submitResult.hasError).toBe(false);

      await orderManagementPage.waitForDialogClosed();

      const exists = await orderManagementPage.orderExists(testOrderName);
      expect(exists).toBe(true);
    });

    test('应该能更换渠道', async ({ orderManagementPage, page }) => {
      await orderManagementPage.openEditDialog(testOrderName);

      const result = await tryChangeSelectValue(page, 'channel-search-select', '渠道');

      if (!result.changed) {
        await orderManagementPage.cancelDialog();
        test.skip(true, '无法更换渠道（可能只有一个选项）');
        return;
      }

      const submitResult = await orderManagementPage.submitForm();
      expect(submitResult.hasSuccess).toBe(true);
      expect(submitResult.hasError).toBe(false);

      await orderManagementPage.waitForDialogClosed();

      const exists = await orderManagementPage.orderExists(testOrderName);
      expect(exists).toBe(true);
    });

    test('应该能同时更换多个关联信息', async ({ orderManagementPage, page }) => {
      await orderManagementPage.openEditDialog(testOrderName);

      let changesMade = 0;

      // 尝试更换平台
      const platformResult = await tryChangeSelectValue(page, 'platform-search-select', '平台');
      if (platformResult.changed) changesMade++;

      // 尝试更换公司
      const companyResult = await tryChangeSelectValue(page, 'company-search-select', '公司');
      if (companyResult.changed) changesMade++;

      // 尝试更换渠道
      const channelResult = await tryChangeSelectValue(page, 'channel-search-select', '渠道');
      if (channelResult.changed) changesMade++;

      if (changesMade === 0) {
        await orderManagementPage.cancelDialog();
        test.skip(true, '没有任何可选择的关联信息选项');
        return;
      }

      const submitResult = await orderManagementPage.submitForm();
      expect(submitResult.hasSuccess).toBe(true);
      expect(submitResult.hasError).toBe(false);

      await orderManagementPage.waitForDialogClosed();

      const exists = await orderManagementPage.orderExists(testOrderName);
      expect(exists).toBe(true);
    });
  });

  test.describe('编辑后列表更新验证', () => {
    test('应该显示更新后的订单名称', async ({ orderManagementPage }) => {
      const newName = `${testOrderName}_列表验证`;
      await orderManagementPage.editOrder(testOrderName, {
        name: newName,
      });

      await expect(async () => {
        const exists = await orderManagementPage.orderExists(newName);
        expect(exists).toBe(true);
      }).toPass({ timeout: TIMEOUTS.DIALOG });

      // 验证旧名称不再存在
      const oldExists = await orderManagementPage.orderExists(testOrderName);
      expect(oldExists).toBe(false);

      testOrderName = newName;
    });

    test('应该显示更新后的预计开始日期', async ({ orderManagementPage }) => {
      const newDate = '2025-04-10';
      await orderManagementPage.editOrder(testOrderName, {
        expectedStartDate: newDate,
      });

      // 验证列表中的日期确实更新了
      await expect(async () => {
        const actualDate = await getOrderExpectedStartDate(orderManagementPage.page, testOrderName);
        expect(actualDate).toBe(newDate);
      }).toPass({ timeout: TIMEOUTS.DIALOG });
    });

    test('编辑后返回列表应该显示更新后的信息', async ({ orderManagementPage }) => {
      const newName = `${testOrderName}_完整验证`;
      const newDate = '2025-05-20';

      await orderManagementPage.editOrder(testOrderName, {
        name: newName,
        expectedStartDate: newDate,
      });

      await expect(async () => {
        const exists = await orderManagementPage.orderExists(newName);
        expect(exists).toBe(true);
      }).toPass({ timeout: TIMEOUTS.DIALOG });

      const oldExists = await orderManagementPage.orderExists(testOrderName);
      expect(oldExists).toBe(false);

      const actualDate = await getOrderExpectedStartDate(orderManagementPage.page, newName);
      expect(actualDate).toBe(newDate);

      testOrderName = newName;
    });
  });

  test.describe('编辑对话框交互验证', () => {
    test('编辑对话框应该预填充现有数据', async ({ orderManagementPage, page }) => {
      await orderManagementPage.openEditDialog(testOrderName);

      const dialog = page.locator('[role="dialog"]');
      await expect(dialog).toBeVisible();

      const nameInput = page.getByLabel(/订单名称|名称/);
      await expect(nameInput).toBeVisible();
      const nameValue = await nameInput.inputValue();
      expect(nameValue).toBe(testOrderName);

      await expect(page.getByLabel(/预计开始日期|开始日期/)).toBeVisible();
      await expect(page.getByRole('button', { name: '更新' })).toBeVisible();
      await expect(page.getByRole('button', { name: '取消' })).toBeVisible();

      await orderManagementPage.cancelDialog();
    });

    test('应该能取消编辑操作', async ({ orderManagementPage, page }) => {
      await orderManagementPage.openEditDialog(testOrderName);

      const modifiedName = `${testOrderName}_已取消`;
      await page.getByLabel(/订单名称|名称/).fill(modifiedName);

      const dialog = page.locator('[role="dialog"]');
      await expect(dialog).toBeVisible();

      await orderManagementPage.cancelDialog();

      await expect(dialog).not.toBeVisible();

      const exists = await orderManagementPage.orderExists(testOrderName);
      expect(exists).toBe(true);

      const modifiedExists = await orderManagementPage.orderExists(modifiedName);
      expect(modifiedExists).toBe(false);
    });

    test('应该显示编辑成功的提示消息', async ({ orderManagementPage }) => {
      const result = await orderManagementPage.editOrder(testOrderName, {
        expectedStartDate: '2025-06-15',
      });

      expect(result.successMessage).toBeDefined();
      expect(result.successMessage?.length).toBeGreaterThan(0);
      console.debug('编辑订单成功消息:', result.successMessage);
    });

    test('应该能通过关闭对话框取消编辑', async ({ orderManagementPage, page }) => {
      await orderManagementPage.openEditDialog(testOrderName);

      const modifiedName = `${testOrderName}_已关闭`;
      await page.getByLabel(/订单名称|名称/).fill(modifiedName);

      const dialog = page.locator('[role="dialog"]');
      await expect(dialog).toBeVisible();

      await page.keyboard.press('Escape');

      await orderManagementPage.waitForDialogClosed();

      const exists = await orderManagementPage.orderExists(testOrderName);
      expect(exists).toBe(true);

      const modifiedExists = await orderManagementPage.orderExists(modifiedName);
      expect(modifiedExists).toBe(false);
    });
  });

  test.describe('错误场景测试', () => {
    test('清空必填字段后应该显示验证错误', async ({ orderManagementPage, page }) => {
      await orderManagementPage.openEditDialog(testOrderName);

      // 清空订单名称
      await page.getByLabel(/订单名称|名称/).fill('');

      // 尝试提交
      const submitButton = page.getByRole('button', { name: /^(创建|更新|保存)$/ });
      await submitButton.click();

      await page.waitForTimeout(TIMEOUTS.LONG);

      // 验证错误提示
      const errorToast = page.locator('[data-sonner-toast][data-type="error"]');
      const hasError = await errorToast.count() > 0;

      // 验证对话框仍然打开（提交失败）
      const dialog = page.locator('[role="dialog"]');
      const isDialogOpen = await dialog.count() > 0;

      expect(hasError || isDialogOpen).toBe(true);

      await orderManagementPage.cancelDialog();
    });

    test('编辑为已存在的订单名称应该显示错误', async ({ orderManagementPage, page }) => {
      // 先创建另一个订单
      const existingOrderName = `已存在订单_${Date.now()}`;
      const created = await createTestOrder(page, existingOrderName);

      if (!created) {
        test.skip(true, '无法创建额外的测试订单');
        return;
      }

      // 尝试编辑当前订单为已存在的名称
      await orderManagementPage.openEditDialog(testOrderName);
      await page.getByLabel(/订单名称|名称/).fill(existingOrderName);

      const result = await orderManagementPage.submitForm();

      // 应该显示错误或失败
      expect(result.hasError).toBe(true);

      // 清理创建的订单
      await orderManagementPage.waitForDialogClosed();
      await orderManagementPage.deleteOrder(existingOrderName);
    });

    test('网络错误时应该显示错误提示', async ({ orderManagementPage, page }) => {
      await orderManagementPage.openEditDialog(testOrderName);

      // 模拟网络离线
      await page.context().setOffline(true);

      // 尝试提交
      const result = await orderManagementPage.submitForm();

      // 恢复网络
      await page.context().setOffline(false);

      // 验证错误消息或网络错误
      expect(result.hasError).toBe(true || result.hasSuccess === false);

      await orderManagementPage.cancelDialog();
    });
  });
});
