import { reactive } from "vue";
import { describe, expect, it } from "vitest";
import type { GoatChainAgent as DimSdkAgent } from "../src/dimsdk/core/acp.ts";
import { createDimSdkStore } from "../src/dimsdk/core/store.ts";
import { useSessionsDialog } from "../src/dimsdk/pages/utils/sessions.ts";

describe("dimsdk sessions dialog", () => {
  it("sorts sessions by updatedAt desc", async () => {
    const agent: DimSdkAgent = { async *receiveMessage() {} };
    const store = createDimSdkStore({
      toolRunner: async () => ({ id: "t", status: "success", output: "ok" }),
      agent: agent as any,
      context: { system: "test", cwd: ".", env: {} },
    });

    const sessionsApi = {
      async list() {
        return [
          { id: "old", updatedAt: 1, title: "old", summary: "", messageCount: 0 },
          { id: "new", updatedAt: 3, title: "new", summary: "", messageCount: 0 },
          { id: "mid", updatedAt: 2, title: "mid", summary: "", messageCount: 0 },
        ] as any;
      },
      async use() {},
      async createNew() {},
      async delete() {},
    };

    const dialog = useSessionsDialog({ store: store as any, sessionsApi: sessionsApi as any });
    await dialog.refreshSessions();

    expect(dialog.sessionsList.value.map((session) => session.id)).toEqual(["new", "mid", "old"]);
  });

  it("does not poll when sessions dialog is closed", async () => {
    const store: any = {
      state: reactive({
        sessionId: "s1",
        context: { cwd: "/work" },
        messages: [],
        revertedMessages: [],
        runningAgentRound: false,
        paused: null,
        approval: { active: null },
      }),
      interrupt() {},
    };

    let listCalls = 0;
    const options: any = {
      store,
      pollIntervalMs: 25,
      sessionsApi: {
        async list() {
          listCalls += 1;
          return [{ id: "s1", updatedAt: Date.now(), title: "s1", summary: "", messageCount: 0 }];
        },
        async use() {},
        async createNew() {},
        async delete() {},
      },
    };

    useSessionsDialog(options);
    await new Promise((resolve) => setTimeout(resolve, 90));
    expect(listCalls).toBe(0);

    options.sessionsApi = undefined;
    await new Promise((resolve) => setTimeout(resolve, 10));
  });

  it("reloads active session when remote messageCount differs", async () => {
    const store: any = {
      state: reactive({
        sessionId: "s1",
        context: { cwd: "/work" },
        messages: [{ id: "m1", role: "user", content: "hi" }],
        revertedMessages: [],
        runningAgentRound: false,
        paused: null,
        approval: { active: null },
      }),
      interrupt() {},
    };

    let reloadCalls = 0;
    const sessionsApi = {
      async list() {
        return [{ id: "s1", updatedAt: 100, title: "s1", summary: "", messageCount: 2 }];
      },
      async reload() {
        reloadCalls += 1;
        store.state.messages = [
          { id: "m1", role: "user", content: "hi" },
          { id: "m2", role: "assistant", parts: [] },
        ];
        return true;
      },
      async use() {},
      async createNew() {},
      async delete() {},
    } as any;

    const dialog = useSessionsDialog({ store, sessionsApi });
    await dialog.refreshSessions();
    expect(reloadCalls).toBe(1);

    await dialog.refreshSessions();
    expect(reloadCalls).toBe(1);
  });

  it("does not reload active session while local reverted messages are pending", async () => {
    const store: any = {
      state: reactive({
        sessionId: "s1",
        context: { cwd: "/work" },
        messages: [{ id: "m1", role: "user", content: "hi" }],
        revertedMessages: [{ id: "m2", role: "assistant", parts: [] }],
        runningAgentRound: false,
        paused: null,
        approval: { active: null },
      }),
      interrupt() {},
    };

    let reloadCalls = 0;
    const sessionsApi = {
      async list() {
        return [{ id: "s1", updatedAt: 100, title: "s1", summary: "", messageCount: 2 }];
      },
      async reload() {
        reloadCalls += 1;
        return true;
      },
      async use() {},
      async createNew() {},
      async delete() {},
    } as any;

    const dialog = useSessionsDialog({ store, sessionsApi });
    await dialog.refreshSessions();
    expect(reloadCalls).toBe(0);
  });
});
