/**
 * Trace page Session-list logic (pure): mapping both server response shapes to the
 * page's Session groups, and partitioning rows by their server-classified category.
 */
import { describe, expect, it } from "vitest";
import type { AgentTracesResponse } from "@prismshadow/penguin-server/api";
import { SIDEBAR_GROUP_PAGE_SIZE, SIDEBAR_PAGE_SIZE } from "../src/lib/session-grouping";
import {
  TRACES_GROUP_PAGE_SIZE,
  TRACES_PAGE_SIZE,
  partitionTraceRows,
  toSessionGroups,
} from "../src/features/traces/trace-sessions";
import type { TraceSessionRow } from "../src/features/traces/trace-sessions";

describe("trace page thresholds", () => {
  it("stay larger than the sidebar's (full-height page column vs narrow sidebar), and bounded", () => {
    expect(TRACES_PAGE_SIZE).toBeGreaterThan(SIDEBAR_PAGE_SIZE);
    expect(TRACES_GROUP_PAGE_SIZE).toBeGreaterThan(SIDEBAR_GROUP_PAGE_SIZE);
    // The fetch limit is TRACES_PAGE_SIZE + 1; the server caps limit at 1000.
    expect(TRACES_PAGE_SIZE + 1).toBeLessThanOrEqual(1000);
  });
});

const S1 = "session-2026-07-05-10-00-00-aabbccdd";
const S2 = "session-2026-07-06-09-00-00-11112222";

describe("toSessionGroups", () => {
  it("paged response: server order kept, titles/classification carried, files re-sorted newest first", () => {
    const res: AgentTracesResponse = {
      dates: [],
      sessions: [
        {
          sessionId: S2,
          title: "标题",
          category: "subagent",
          workspace: "/ws/one",
          files: [
            { index: 1, date: "2026-07-06", sizeBytes: 10 },
            { index: 2, date: "2026-07-07", sizeBytes: 20 },
          ],
        },
        {
          sessionId: S1,
          category: "active",
          workspace: "",
          files: [{ index: 1, date: "2026-07-05", sizeBytes: 5 }],
        },
      ],
      totalSessions: 12,
    };
    const groups = toSessionGroups(res);
    expect(groups.map((g) => g.sessionId)).toEqual([S2, S1]);
    expect(groups[0]!.title).toBe("标题");
    expect(groups[0]!.category).toBe("subagent");
    expect(groups[0]!.workspace).toBe("/ws/one");
    expect(groups[0]!.files.map((f) => f.index)).toEqual([2, 1]); // newest first for display
    expect(groups[1]!.title).toBeUndefined();
  });

  it("legacy response: flattens date groups (merging a Session's files across dates), Sessions sorted by id descending, classification defaulted", () => {
    const res: AgentTracesResponse = {
      dates: [
        {
          date: "2026-07-06",
          sessions: [
            { sessionId: S2, files: [{ index: 1, sizeBytes: 1 }] },
            { sessionId: S1, files: [{ index: 2, sizeBytes: 2 }] },
          ],
        },
        { date: "2026-07-05", sessions: [{ sessionId: S1, files: [{ index: 1, sizeBytes: 3 }] }] },
      ],
    };
    const groups = toSessionGroups(res);
    expect(groups.map((g) => g.sessionId)).toEqual([S2, S1]);
    // S1's files merged across both dates, each carrying its own date, newest first.
    expect(groups[1]!.files).toEqual([
      { index: 2, date: "2026-07-06", sizeBytes: 2 },
      { index: 1, date: "2026-07-05", sizeBytes: 3 },
    ]);
    // No classification in the legacy shape: rows default to the active bucket / unknown workspace.
    expect(groups[0]!.category).toBe("active");
    expect(groups[0]!.workspace).toBe("");
  });
});

describe("partitionTraceRows", () => {
  it("splits rows by their server-classified category, preserving input order", () => {
    const row = (sessionId: string, category: TraceSessionRow["category"]): TraceSessionRow => ({
      sessionId,
      category,
      workspace: "",
      files: [],
      agentId: "a1",
    });
    const parts = partitionTraceRows([
      row("s-4", "archived"),
      row("s-3", "active"),
      row("s-2", "subagent"),
      row("s-1", "active"),
    ]);
    expect(parts.active.map((r) => r.sessionId)).toEqual(["s-3", "s-1"]);
    expect(parts.subagent.map((r) => r.sessionId)).toEqual(["s-2"]);
    expect(parts.schedule).toEqual([]);
    expect(parts.archived.map((r) => r.sessionId)).toEqual(["s-4"]);
  });
});
