/**
 * 属性测试：Tab 切换状态保持 round-trip
 *
 * Feature: admin-web-restructure, Property 2: Tab 切换状态保持 round-trip
 * **Validates: Requirements 3.5**
 *
 * 对于任意 ETL 任务管理的 Tab 视图，在某个 Tab 中设置筛选条件后
 * 切换到另一个 Tab 再切回来，原 Tab 的筛选条件应保持不变。
 *
 * 策略：Mock 子组件为带 text input 的有状态组件，
 * 通过输入文本 → 切换 Tab → 切回 → 验证文本保留来证明状态保持。
 */

import { useState } from "react";
import { describe, it, expect, vi, afterEach } from "vitest";
import { render, screen, fireEvent, cleanup } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import * as fc from "fast-check";

/* ------------------------------------------------------------------ */
/*  Mock 子组件：带有状态的简单输入框                                    */
/* ------------------------------------------------------------------ */

function StatefulTab({ tabKey }: { tabKey: string }) {
  const [value, setValue] = useState("");
  return (
    <div data-testid={`tab-panel-${tabKey}`}>
      <input
        data-testid={`state-input-${tabKey}`}
        value={value}
        onChange={(e) => setValue(e.target.value)}
      />
    </div>
  );
}

vi.mock("../pages/TaskConfig", () => ({
  default: () => <StatefulTab tabKey="config" />,
}));
vi.mock("../pages/TaskManager", () => ({
  default: () => <StatefulTab tabKey="manager" />,
}));
vi.mock("../pages/ETLStatus", () => ({
  default: () => <StatefulTab tabKey="status" />,
}));

import ETLTasks from "../pages/ETLTasks";

/* ------------------------------------------------------------------ */
/*  常量                                                               */
/* ------------------------------------------------------------------ */

const VALID_TABS = ["config", "manager", "status"] as const;
type TabKey = (typeof VALID_TABS)[number];

const TAB_LABELS: Record<TabKey, string> = {
  config: "任务配置",
  manager: "任务管理",
  status: "ETL 状态",
};

/* ------------------------------------------------------------------ */
/*  辅助函数                                                           */
/* ------------------------------------------------------------------ */

/** 点击指定 Tab */
function clickTab(tabKey: TabKey) {
  const tabElements = document.querySelectorAll(".ant-tabs-tab");
  for (const el of tabElements) {
    if (el.textContent?.includes(TAB_LABELS[tabKey])) {
      fireEvent.click(el);
      return;
    }
  }
  throw new Error(`Tab "${tabKey}" not found`);
}

/* ------------------------------------------------------------------ */
/*  每次测试后清理 DOM                                                  */
/* ------------------------------------------------------------------ */

afterEach(() => {
  cleanup();
});

/* ------------------------------------------------------------------ */
/*  属性测试                                                           */
/* ------------------------------------------------------------------ */

// DOM 渲染属性测试：numRuns=20 覆盖所有 tab 组合多次，避免 jsdom 超时
const PBT_NUM_RUNS = 20;
const PBT_TIMEOUT = 30_000;

describe("Property 2: Tab 切换状态保持 round-trip", () => {
  // 生成器：从有效 tab 值中随机选取两个不同的 tab
  const distinctTabPairArb = fc
    .tuple(fc.constantFrom(...VALID_TABS), fc.constantFrom(...VALID_TABS))
    .filter(([a, b]) => a !== b);

  // 生成器：模拟用户输入的筛选条件文本
  // 使用 constantFrom 避免 fast-check v4 API 兼容性问题（char/stringOf 已移除）
  const inputTextArb = fc.constantFrom(
    "hello", "test-filter", "ETL_001", "搜索关键词", "abc123",
    "x", "long-filter-value-example", "special!@#", "  spaces  ", "UPPER",
  );

  it("在某 Tab 设置状态 → 切换到另一 Tab → 切回 → 状态保持不变", () => {
    fc.assert(
      fc.property(distinctTabPairArb, inputTextArb, ([sourceTab, otherTab], text) => {
        cleanup();

        // 渲染页面，初始 Tab 为 sourceTab
        render(
          <MemoryRouter initialEntries={[`/etl-tasks?tab=${sourceTab}`]}>
            <ETLTasks />
          </MemoryRouter>,
        );

        // 1. 在 sourceTab 的输入框中输入文本
        const input = screen.getByTestId(`state-input-${sourceTab}`) as HTMLInputElement;
        fireEvent.change(input, { target: { value: text } });
        expect(input.value).toBe(text);

        // 2. 切换到 otherTab
        clickTab(otherTab);

        // 3. 切回 sourceTab
        clickTab(sourceTab);

        // 4. 验证 sourceTab 的输入框文本保持不变
        const inputAfter = screen.getByTestId(`state-input-${sourceTab}`) as HTMLInputElement;
        expect(inputAfter.value).toBe(text);

        cleanup();
      }),
      { numRuns: PBT_NUM_RUNS },
    );
  }, PBT_TIMEOUT);
});
