import { describe, it, expect, vi, beforeEach } from "vitest";

const invoke = vi.fn();
vi.mock("@tauri-apps/api/core", () => ({
  invoke: (...args: unknown[]) => invoke(...args),
  Channel: class {
    onmessage: ((chunk: unknown) => void) | null = null;
  },
}));

import { TauriTicketGateway } from "./ticket";

describe("TauriTicketGateway invoke payloads", () => {
  beforeEach(() => invoke.mockReset().mockResolvedValue({ items: [] }));

  it("bulk status wraps refs and status in the request DTO", async () => {
    await new TauriTicketGateway().bulkUpdateStatus(
      "proj-1",
      ["#1", "#2"],
      "inProgress",
    );

    expect(invoke).toHaveBeenCalledWith("ticket_bulk_update_status", {
      request: {
        projectId: "proj-1",
        refs: ["#1", "#2"],
        status: "inProgress",
      },
    });
  });

  it("bulk delete wraps refs in the request DTO", async () => {
    await new TauriTicketGateway().bulkDelete("proj-1", ["#3", "#4"]);

    expect(invoke).toHaveBeenCalledWith("ticket_bulk_delete", {
      request: {
        projectId: "proj-1",
        refs: ["#3", "#4"],
      },
    });
  });

  it("passes createdBy through the ticket list request DTO", async () => {
    await new TauriTicketGateway().list("proj-1", {
      createdBy: { kind: "agent", agentId: "agent-1" },
    });

    expect(invoke).toHaveBeenCalledWith("ticket_list", {
      request: {
        projectId: "proj-1",
        statuses: [],
        priorities: [],
        createdBy: { kind: "agent", agentId: "agent-1" },
      },
    });
  });

  it("normalizes legacy ticket list rows that omit assignedAgentIds and createdBy", async () => {
    invoke.mockResolvedValueOnce({
      items: [
        {
          ref: "#12",
          path: ".ideai/tickets/12/issue.md",
          title: "Legacy row",
          status: "open",
          priority: "medium",
          updatedAt: 1,
        },
      ],
    });

    const list = await new TauriTicketGateway().list("proj-1");

    expect(list.items[0]?.assignedAgentIds).toEqual([]);
    expect(list.items[0]?.createdBy).toEqual({ kind: "user" });
  });

  it("wraps ticket attachment commands in the request DTO", async () => {
    const gateway = new TauriTicketGateway();

    await gateway.addAttachment(
      "proj-1",
      "#12",
      "/tmp/note.txt",
      3,
      "text/plain",
    );
    await gateway.readAttachment("proj-1", "#12", "att-1");
    await gateway.markAttachmentSummarized("proj-1", "#12", "att-1", 4);

    expect(invoke).toHaveBeenNthCalledWith(1, "ticket_attachment_add", {
      request: {
        projectId: "proj-1",
        ref: "#12",
        path: "/tmp/note.txt",
        expectedVersion: 3,
        mime: "text/plain",
      },
    });
    expect(invoke).toHaveBeenNthCalledWith(2, "ticket_attachment_read", {
      request: {
        projectId: "proj-1",
        ref: "#12",
        attachmentId: "att-1",
      },
    });
    expect(invoke).toHaveBeenNthCalledWith(
      3,
      "ticket_attachment_mark_summarized",
      {
        request: {
          projectId: "proj-1",
          ref: "#12",
          attachmentId: "att-1",
          expectedVersion: 4,
        },
      },
    );
  });

  it("normalizes legacy ticket payloads that omit array fields and actors", async () => {
    invoke.mockResolvedValueOnce({
      id: "issue-1",
      ref: "#12",
      number: 12,
      title: "Legacy",
      description: "",
      status: "open",
      priority: "medium",
      createdAt: 1,
      updatedAt: 1,
      version: 1,
    });

    const ticket = await new TauriTicketGateway().read("proj-1", "#12", true);

    expect(ticket.links).toEqual([]);
    expect(ticket.assignedAgentIds).toEqual([]);
    expect(ticket.attachments).toEqual([]);
    expect(ticket.createdBy).toEqual({ kind: "user" });
    expect(ticket.updatedBy).toEqual({ kind: "user" });
  });

  it("normalizes malformed ticket actors", async () => {
    invoke.mockResolvedValueOnce({
      id: "issue-1",
      ref: "#12",
      number: 12,
      title: "Legacy",
      description: "",
      status: "open",
      priority: "medium",
      createdBy: { kind: "agent" },
      updatedBy: { kind: "unknown" },
      createdAt: 1,
      updatedAt: 1,
      version: 1,
    });

    const ticket = await new TauriTicketGateway().read("proj-1", "#12", true);

    expect(ticket.createdBy).toEqual({ kind: "user" });
    expect(ticket.updatedBy).toEqual({ kind: "user" });
  });
});
