import { TIMEOUTS } from '../../utils/timeouts';
import { test, expect } from '../../utils/test-setup';
import type { Page } from '@playwright/test';
import { AdminLoginPage } from '../../pages/admin/login.page';
import { TalentMiniPage } from '../../pages/mini/talent-mini.page';
import type { TalentOrderData, TalentOrderDetailData } from '../../pages/mini/talent-mini.page';

/**
 * 跨端数据同步 E2E 测试 - 人员添加
 *
 * 测试目标：验证后台添加残疾人到订单后，人才小程序能否正确显示关联的订单
 *
 * 测试流程：
 * 1. 后台操作：登录 → 打开订单详情 → 添加残疾人 → 验证添加成功
 * 2. 小程序验证：登录 → 导航到"我的订单" → 验证订单显示
 *
 * 测试要点：
 * - 使用两个独立的 browser context（后台和小程序）
 * - 记录数据同步时间
 * - 使用 data-testid 选择器
 * - 验证两步确认流程（选择残疾人 → 确认添加）
 *
 * 关键发现（来自 Task 0 Playwright MCP 探索）：
 * 1. 添加人员需要两步确认：
 *    - 第一步：选择残疾人 → "确认选择"
 *    - 第二步：待添加人员列表 → "确认添加"
 * 2. 默认薪资为 5000
 * 3. 入职日期自动设置为当天
 * 4. 已绑定人员的复选框自动禁用
 */

// 测试常量
const TEST_SYNC_TIMEOUT = 10000; // 数据同步等待时间（ms）- AC 要求 ≤ 10 秒
const TEST_POLL_INTERVAL = 500; // 轮询检查间隔（ms）
const TEST_ORDER_ID = 724; // 测试订单 ID（使用已存在的订单）
const TEST_ORDER_NAME = 'Epic13验证测试_1768403960000_Story13.2已编辑'; // 测试订单名称

// 人才小程序登录凭据（需要与添加的残疾人关联）
const TALENT_LOGIN_PHONE = '13800119311'; // 测试残疾人_1768346764677_11_9311 的手机号
const TALENT_LOGIN_PASSWORD = process.env.TEST_TALENT_PASSWORD || 'password123'; // 默认测试密码

/**
 * 后台登录辅助函数
 */
async function loginAdmin(page: Page, testUsers: { admin: { username: string; password: string } }) {
  const adminLoginPage = new AdminLoginPage(page);
  await adminLoginPage.goto();
  await adminLoginPage.page.getByPlaceholder('请输入用户名').fill(testUsers.admin.username);
  await adminLoginPage.page.getByPlaceholder('请输入密码').fill(testUsers.admin.password);
  await adminLoginPage.page.getByRole('button', { name: '登录' }).click();
  await adminLoginPage.page.waitForURL('**/admin/dashboard', { timeout: TIMEOUTS.PAGE_LOAD });
  console.debug('[后台] 登录成功');
}

/**
 * 人才小程序登录辅助函数
 */
async function loginTalentMini(page: Page) {
  const talentMiniPage = new TalentMiniPage(page);
  await talentMiniPage.goto();
  await talentMiniPage.login(TALENT_LOGIN_PHONE, TALENT_LOGIN_PASSWORD);
  await talentMiniPage.expectLoginSuccess();
  console.debug('[人才小程序] 登录成功');
}

// 测试状态管理（使用闭包替代 process.env）
interface TestState {
  personId: number | null;
  personName: string | null;
  syncTime: number | null;
}

const testState: TestState = {
  personId: null,
  personName: null,
  syncTime: null,
};

test.describe('跨端数据同步测试 - 后台添加人员到人才小程序', () => {
  // 在所有测试后清理测试数据
  test.afterAll(async () => {
    // 清理测试状态
    testState.personId = null;
    testState.personName = null;
    testState.syncTime = null;
    console.debug('[清理] 测试数据已清理');
  });

  test.describe.serial('后台添加人员', () => {
    test('应该成功打开订单详情并添加残疾人', async ({ adminPage, testUsers }) => {
      // 记录开始时间
      const startTime = Date.now();

      // 1. 后台登录（使用辅助函数）
      await loginAdmin(adminPage, testUsers);

      // 2. 导航到订单管理页面
      await adminPage.goto('/admin/orders');
      await adminPage.waitForSelector('table tbody tr', { state: 'visible', timeout: TIMEOUTS.PAGE_LOAD });
      console.debug('[后台] 导航到订单管理页面');

      // 3. 打开订单详情对话框
      // 点击订单的"打开菜单"按钮
      await adminPage.getByTestId(`order-menu-trigger-${TEST_ORDER_ID}`).click();
      await adminPage.waitForTimeout(TIMEOUTS.VERY_SHORT);
      console.debug(`[后台] 打开订单 ${TEST_ORDER_ID} 的菜单`);

      // 点击"查看详情"菜单项
      await adminPage.getByTestId(`view-order-detail-button-${TEST_ORDER_ID}`).click();
      await adminPage.waitForSelector('[role="dialog"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });
      console.debug('[后台] 打开订单详情对话框');

      // 4. 点击"添加人员"按钮
      await adminPage.getByTestId('order-detail-card-add-persons-button').click();
      await adminPage.waitForSelector('text=选择残疾人', { state: 'visible', timeout: TIMEOUTS.DIALOG });
      console.debug('[后台] 打开选择残疾人对话框');

      // 5. 选择残疾人
      // 注意：已绑定人员的复选框会被禁用
      // 动态选择第一个未绑定的残疾人
      const checkboxes = adminPage.locator('[data-testid^="person-checkbox-"]:not([disabled])');
      const firstAvailable = checkboxes.first();
      const testPersonIdAttr = await firstAvailable.getAttribute('data-testid');
      const testPersonId = parseInt(testPersonIdAttr?.replace('person-checkbox-', '') || '0');
      await firstAvailable.click();
      console.debug(`[后台] 选择残疾人 ID: ${testPersonId}`);

      // 6. 点击"确认选择"按钮
      // 人员进入"待添加人员列表"
      await adminPage.getByTestId('confirm-batch-button').click();
      await adminPage.waitForTimeout(TIMEOUTS.MEDIUM);
      console.debug('[后台] 确认选择残疾人');

      // 7. 验证待添加人员列表显示
      // 检查是否有"待添加人员列表"或"确认添加"按钮
      const confirmAddButton = adminPage.getByTestId('confirm-add-persons-button');
      await expect(confirmAddButton).toBeVisible();
      console.debug('[后台] 待添加人员列表已显示');

      // 8. 点击"确认添加"按钮完成绑定
      await confirmAddButton.click();
      await adminPage.waitForTimeout(TIMEOUTS.LONG);

      // 9. 验证 Toast 通知
      // 使用 filter 精确匹配"批量添加人员成功"消息（避免匹配"已添加到待添加列表"）
      const successToast = adminPage.locator('[data-sonner-toast][data-type="success"]').filter({ hasText: '批量添加人员成功' });
      await expect(successToast).toBeVisible({ timeout: TIMEOUTS.VERY_LONG });
      const toastMessage = await successToast.textContent();
      console.debug(`[后台] Toast 消息: ${toastMessage}`);
      expect(toastMessage).toContain('批量添加人员成功');

      // 10. 验证绑定人员列表更新
      // 检查订单详情对话框中的绑定人员列表
      // 应该能看到新添加的人员
      const personRow = adminPage.locator('table tbody tr').filter({ hasText: '测试残疾人_1768346764677_11_9311' });
      await expect(personRow).toBeVisible();
      console.debug('[后台] 人员已成功添加到绑定人员列表');

      // 记录测试数据
      testState.personId = testPersonId;
      testState.personName = '测试残疾人_1768346764677_11_9311';

      const endTime = Date.now();
      const duration = endTime - startTime;
      console.debug(`[后台] 添加人员完成，耗时: ${duration}ms`);
    });
  });

  test.describe.serial('人才小程序验证', () => {
    test('应该在小程序中显示关联的订单', async ({ talentMiniPage: page }) => {
      // 创建 TalentMiniPage 对象
      const talentMini = new TalentMiniPage(page);

      // 1. 人才小程序登录
      await loginTalentMini(page);

      // 2. 记录同步开始时间
      const syncStartTime = Date.now();

      // 3. 导航到"我的订单"页面
      await talentMini.navigateToMyOrders();
      console.debug('[人才小程序] 已导航到我的订单页面');

      // 4. 验证订单显示（使用轮询等待）
      // 由于数据同步可能有延迟，使用轮询检查
      const orderFound = await talentMini.waitForOrderToAppear(TEST_ORDER_NAME, TEST_SYNC_TIMEOUT);

      const syncEndTime = Date.now();
      testState.syncTime = syncEndTime - syncStartTime;

      // 5. 验证订单存在
      expect(orderFound, `订单 "${TEST_ORDER_NAME}" 应该在人才小程序中显示`).toBe(true);
      console.debug(`[人才小程序] 订单已同步，耗时: ${testState.syncTime}ms`);

      // 6. 验证同步时间符合要求
      expect(testState.syncTime).toBeLessThanOrEqual(TEST_SYNC_TIMEOUT);
      console.debug(`[验证] 数据同步时间 ${testState.syncTime}ms 符合要求（≤ ${TEST_SYNC_TIMEOUT}ms）`);
    });

    test('应该在小程序订单详情中显示完整信息', async ({ talentMiniPage: page }) => {
      // 创建 TalentMiniPage 对象
      const talentMini = new TalentMiniPage(page);

      // 前置条件：已登录并在我的订单页面
      await loginTalentMini(page);
      await talentMini.navigateToMyOrders();

      // 1. 导航到"我的订单"并找到测试订单
      const orders: TalentOrderData[] = await talentMini.getMyOrders();
      const testOrder = orders.find(order => order.name === TEST_ORDER_NAME);

      expect(testOrder, `应该找到订单 "${TEST_ORDER_NAME}"`).toBeDefined();
      console.debug(`[人才小程序] 找到订单: ${testOrder?.name}`);

      // 2. 点击订单详情
      const orderId = await talentMini.openOrderDetail(TEST_ORDER_NAME);
      expect(orderId).toBeTruthy();
      console.debug(`[人才小程序] 已打开订单详情: ${orderId}`);

      // 3. 验证订单信息完整性
      const detail: TalentOrderDetailData = await talentMini.getOrderDetail();

      // 验证订单名称
      expect(detail.name).toBe(TEST_ORDER_NAME);
      console.debug(`[人才小程序] 订单名称: ${detail.name}`);

      // 验证公司名称
      expect(detail.companyName).toBeDefined();
      console.debug(`[人才小程序] 公司名称: ${detail.companyName}`);

      // 验证订单状态
      expect(detail.status).toBeDefined();
      console.debug(`[人才小程序] 订单状态: ${detail.status}`);

      console.debug('[人才小程序] 订单详情信息验证完成');
    });
  });

  test.describe.serial('数据同步时效性验证', () => {
    test('应该在合理时间内完成数据同步（≤ 10 秒）', async () => {
      // 此测试专门验证数据同步时效性
      // AC6: 数据应在 5 秒内同步，最多等待 10 秒

      console.debug('[验证] 数据同步时效性测试');
      console.debug(`[验证] 要求: ≤ ${TEST_SYNC_TIMEOUT}ms`);
      console.debug(`[验证] 实际: ${testState.syncTime}ms`);
      console.debug(`[验证] 轮询间隔: ${TEST_POLL_INTERVAL}ms`);

      if (testState.syncTime !== null) {
        expect(testState.syncTime).toBeLessThanOrEqual(TEST_SYNC_TIMEOUT);
        console.debug(`[验证] ✅ 数据同步时间符合要求`);
      } else {
        console.warn('[验证] ⚠️ 未记录到同步时间，请检查测试执行');
      }
    });
  });

  test.describe.serial('多人员添加同步验证', () => {
    test('应该支持批量添加多个残疾人', async ({ adminPage, testUsers }) => {
      // AC3: 多人员添加同步验证
      // 此测试验证添加多个残疾人后小程序的同步情况

      // 1. 后台登录
      await loginAdmin(adminPage, testUsers);

      // 2. 打开订单详情
      await adminPage.goto('/admin/orders');
      await adminPage.getByTestId(`order-menu-trigger-${TEST_ORDER_ID}`).click();
      await adminPage.waitForTimeout(TIMEOUTS.VERY_SHORT);
      await adminPage.getByTestId(`view-order-detail-button-${TEST_ORDER_ID}`).click();
      await adminPage.waitForSelector('[role="dialog"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });

      // 3. 点击"添加人员"按钮
      await adminPage.getByTestId('order-detail-card-add-persons-button').click();
      await adminPage.waitForSelector('text=选择残疾人', { state: 'visible', timeout: TIMEOUTS.DIALOG });

      // 4. 选择多个残疾人
      // 选择第一个和第二个可用的残疾人（未被绑定的）
      const checkboxes = adminPage.locator('[data-testid^="person-checkbox-"]:not([disabled])');
      const checkboxCount = await checkboxes.count();

      if (checkboxCount >= 2) {
        await checkboxes.nth(0).click();
        await checkboxes.nth(1).click();
        console.debug(`[后台] 已选择 ${Math.min(2, checkboxCount)} 个残疾人`);

        // 点击"确认选择"
        await adminPage.getByTestId('confirm-batch-button').click();
        await adminPage.waitForTimeout(TIMEOUTS.MEDIUM);

        // 点击"确认添加"
        await adminPage.getByTestId('confirm-add-persons-button').click();
        await adminPage.waitForTimeout(TIMEOUTS.LONG);

        // 验证成功 Toast
        const successToast = adminPage.locator('[data-sonner-toast][data-type="success"]').filter({ hasText: '批量添加人员成功' });
        await expect(successToast).toBeVisible({ timeout: TIMEOUTS.VERY_LONG });
        console.debug('[后台] 多人员添加成功');
      } else {
        console.debug(`[后台] 可用残疾人不足 2 个，跳过多人员测试`);
      }
    });
  });
});
