import { describe, expect, it } from "vitest";
import type { SessionInfo } from "../src/core/session-manager.js";
import { filterAndSortSessions } from "../src/modes/interactive/components/session-selector-search.js";

function makeSession(
  overrides: Partial<SessionInfo> & {
    id: string;
    modified: Date;
    allMessagesText: string;
  },
): SessionInfo {
  return {
    path: `/tmp/${overrides.id}.jsonl`,
    id: overrides.id,
    cwd: overrides.cwd ?? "",
    name: overrides.name,
    created: overrides.created ?? new Date(0),
    modified: overrides.modified,
    messageCount: overrides.messageCount ?? 1,
    firstMessage: overrides.firstMessage ?? "(no messages)",
    allMessagesText: overrides.allMessagesText,
  };
}

describe("session selector search", () => {
  it("filters by quoted phrase with whitespace normalization", () => {
    const sessions: SessionInfo[] = [
      makeSession({
        id: "a",
        modified: new Date("2026-01-01T00:00:00.000Z"),
        allMessagesText: "node\n\n   cve was discussed",
      }),
      makeSession({
        id: "b",
        modified: new Date("2026-01-02T00:00:00.000Z"),
        allMessagesText: "node something else",
      }),
    ];

    const result = filterAndSortSessions(sessions, '"node cve"', "recent");
    expect(result.map((s) => s.id)).toEqual(["a"]);
  });

  it("filters by regex (re:) and is case-insensitive", () => {
    const sessions: SessionInfo[] = [
      makeSession({
        id: "a",
        modified: new Date("2026-01-02T00:00:00.000Z"),
        allMessagesText: "Brave is great",
      }),
      makeSession({
        id: "b",
        modified: new Date("2026-01-03T00:00:00.000Z"),
        allMessagesText: "bravery is not the same",
      }),
    ];

    const result = filterAndSortSessions(sessions, "re:\\bbrave\\b", "recent");
    expect(result.map((s) => s.id)).toEqual(["a"]);
  });

  it("recent sort preserves input order", () => {
    const sessions: SessionInfo[] = [
      makeSession({
        id: "newer",
        modified: new Date("2026-01-03T00:00:00.000Z"),
        allMessagesText: "brave",
      }),
      makeSession({
        id: "older",
        modified: new Date("2026-01-01T00:00:00.000Z"),
        allMessagesText: "brave",
      }),
      makeSession({
        id: "nomatch",
        modified: new Date("2026-01-04T00:00:00.000Z"),
        allMessagesText: "something else",
      }),
    ];

    const result = filterAndSortSessions(sessions, '"brave"', "recent");
    expect(result.map((s) => s.id)).toEqual(["newer", "older"]);
  });

  it("relevance sort orders by score and tie-breaks by modified desc", () => {
    const sessions: SessionInfo[] = [
      makeSession({
        id: "late",
        modified: new Date("2026-01-03T00:00:00.000Z"),
        allMessagesText: "xxxx brave",
      }),
      makeSession({
        id: "early",
        modified: new Date("2026-01-01T00:00:00.000Z"),
        allMessagesText: "brave xxxx",
      }),
    ];

    const result1 = filterAndSortSessions(sessions, '"brave"', "relevance");
    expect(result1.map((s) => s.id)).toEqual(["early", "late"]);

    const tieSessions: SessionInfo[] = [
      makeSession({
        id: "newer",
        modified: new Date("2026-01-03T00:00:00.000Z"),
        allMessagesText: "brave",
      }),
      makeSession({
        id: "older",
        modified: new Date("2026-01-01T00:00:00.000Z"),
        allMessagesText: "brave",
      }),
    ];

    const result2 = filterAndSortSessions(tieSessions, '"brave"', "relevance");
    expect(result2.map((s) => s.id)).toEqual(["newer", "older"]);
  });

  it("returns empty list for invalid regex", () => {
    const sessions: SessionInfo[] = [
      makeSession({
        id: "a",
        modified: new Date("2026-01-01T00:00:00.000Z"),
        allMessagesText: "brave",
      }),
    ];

    const result = filterAndSortSessions(sessions, "re:(", "recent");
    expect(result).toEqual([]);
  });

  describe("name filter", () => {
    const sessions: SessionInfo[] = [
      makeSession({
        id: "named1",
        name: "My Project",
        modified: new Date("2026-01-03T00:00:00.000Z"),
        allMessagesText: "blueberry",
      }),
      makeSession({
        id: "named2",
        name: "Another Named",
        modified: new Date("2026-01-02T00:00:00.000Z"),
        allMessagesText: "blueberry",
      }),
      makeSession({
        id: "other1",
        modified: new Date("2026-01-04T00:00:00.000Z"),
        allMessagesText: "blueberry",
      }),
      makeSession({
        id: "other2",
        modified: new Date("2026-01-01T00:00:00.000Z"),
        allMessagesText: "blueberry",
      }),
    ];

    it("returns all sessions when nameFilter is 'all'", () => {
      const result = filterAndSortSessions(sessions, "", "recent", "all");
      expect(result.map((session) => session.id)).toEqual([
        "named1",
        "named2",
        "other1",
        "other2",
      ]);
    });

    it("returns only named sessions when nameFilter is 'named'", () => {
      const result = filterAndSortSessions(sessions, "", "recent", "named");
      expect(result.map((session) => session.id)).toEqual(["named1", "named2"]);
    });

    it("applies name filter before search query", () => {
      const result = filterAndSortSessions(
        sessions,
        "blueberry",
        "recent",
        "named",
      );
      expect(result.map((session) => session.id)).toEqual(["named1", "named2"]);
    });

    it("excludes whitespace-only names from named filter", () => {
      const sessionsWithWhitespace: SessionInfo[] = [
        makeSession({
          id: "whitespace",
          name: "   ",
          modified: new Date("2026-01-01T00:00:00.000Z"),
          allMessagesText: "test",
        }),
        makeSession({
          id: "empty",
          name: "",
          modified: new Date("2026-01-02T00:00:00.000Z"),
          allMessagesText: "test",
        }),
        makeSession({
          id: "named",
          name: "Real Name",
          modified: new Date("2026-01-03T00:00:00.000Z"),
          allMessagesText: "test",
        }),
      ];

      const result = filterAndSortSessions(
        sessionsWithWhitespace,
        "",
        "recent",
        "named",
      );
      expect(result.map((session) => session.id)).toEqual(["named"]);
    });
  });
});
