import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { cleanup, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import type { ReactNode } from "react";
import { MemoryRouter, Route, Routes } from "react-router-dom";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

vi.mock("./lib/api", () => ({
  clearPlatformSession: vi.fn(),
  confirmTask: vi.fn(),
  createTask: vi.fn(),
  deleteTask: vi.fn(),
  getHistoryTasks: vi.fn(),
  getPlatformReadiness: vi.fn(),
  getPlatformSession: vi.fn(),
  getTask: vi.fn(),
  getTaskCandidates: vi.fn(),
  getTaskReport: vi.fn(),
  preparePlatform: vi.fn(),
  retryTaskPlatform: vi.fn()
}));

import { NewTaskPage, SessionPreparePage } from "./App";
import {
  clearPlatformSession,
  getHistoryTasks,
  getPlatformReadiness,
  getPlatformSession,
  preparePlatform
} from "./lib/api";

function renderWithProviders(node: ReactNode, initialEntries?: string[]) {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        retry: false
      }
    }
  });

  return render(
    <QueryClientProvider client={queryClient}>
      {initialEntries ? (
        <MemoryRouter initialEntries={initialEntries}>{node}</MemoryRouter>
      ) : (
        <MemoryRouter>{node}</MemoryRouter>
      )}
    </QueryClientProvider>
  );
}

describe("task composer and session console", () => {
  beforeEach(() => {
    vi.mocked(getPlatformReadiness).mockResolvedValue({
      platforms: [
        {
          platform: "tmall",
          ready: true,
          status: "ready",
          searchRequirement: "recommended",
          reason: "当前工作区存在可复用会话，创建任务时会再次校验。",
          lastPreparedAt: "2026-04-02T12:00:00.000Z",
          expiresAt: "2026-04-03T12:00:00.000Z"
        },
        {
          platform: "jd",
          ready: false,
          status: "missing",
          searchRequirement: "required",
          reason: "需要先完成会话准备，否则系统会标记为 SearchBlocked。"
        }
      ]
    } as any);
    vi.mocked(getHistoryTasks).mockResolvedValue({
      tasks: [
        {
          taskId: "task-1",
          query: "Nintendo Switch 2",
          taskStatus: "Completed",
          updatedAt: "2026-04-02T12:00:00.000Z",
          hasReport: true,
          defaultReportVersion: 2,
          failedPlatforms: [],
          blockedPlatforms: []
        },
        {
          taskId: "task-2",
          query: "DJI Pocket 3",
          taskStatus: "AwaitingConfirmation",
          updatedAt: "2026-04-02T11:30:00.000Z",
          hasReport: false,
          failedPlatforms: [],
          blockedPlatforms: ["jd"]
        }
      ]
    } as any);
    vi.mocked(getPlatformSession).mockResolvedValue({
      session: {
        platform: "jd",
        ready: true,
        status: "ready",
        searchRequirement: "required",
        scope: "workspace",
        ttlHours: 24,
        lastPreparedAt: "2026-04-02T10:00:00.000Z",
        expiresAt: "2026-04-03T10:00:00.000Z",
        encryptedSnapshotAvailable: true,
        cipherLabel: "mock-aes-gcm-v1"
      }
    } as any);
    vi.mocked(clearPlatformSession).mockResolvedValue(undefined);
    vi.mocked(preparePlatform).mockResolvedValue({
      platform: "jd",
      session_ready: true,
      status: "ready",
      last_prepared_at: "2026-04-02T10:00:00.000Z",
      expires_at: "2026-04-03T10:00:00.000Z",
      encrypted_snapshot_available: true
    } as any);
  });

  afterEach(() => {
    cleanup();
    vi.clearAllMocks();
  });

  it("shows readiness details and recent task shortcuts on the new task page", async () => {
    renderWithProviders(<NewTaskPage />);

    expect(await screen.findByText("最近任务捷径")).toBeInTheDocument();
    expect(await screen.findByText("Nintendo Switch 2")).toBeInTheDocument();
    expect(await screen.findByText("DJI Pocket 3")).toBeInTheDocument();
    expect(await screen.findByText("搜索要求：建议预热")).toBeInTheDocument();
    expect(
      await screen.findByText(/当前工作区已有可复用会话，有效至/)
    ).toBeInTheDocument();
  });

  it("shows session details and allows clearing the current session", async () => {
    const user = userEvent.setup();

    renderWithProviders(
      <Routes>
        <Route element={<SessionPreparePage />} path="/sessions/:platform/prepare" />
      </Routes>,
      ["/sessions/jd/prepare?from=/tasks/new"]
    );

    expect(await screen.findByText("已加密保存")).toBeInTheDocument();
    expect(screen.getByText(/完成后将返回：\/tasks\/new/)).toBeInTheDocument();

    await user.click(screen.getByRole("button", { name: "清理当前会话" }));

    await waitFor(() => {
      expect(clearPlatformSession).toHaveBeenCalledWith("jd");
    });
  });
});
