import { beforeEach, describe, expect, it, vi } from "vitest";
import { SystemRole } from "@capakraken/shared";

import { executeTool } from "./assistant-tools-broadcast-send-test-helpers.js";
import { createToolContext } from "./assistant-tools-notification-test-helpers.js";

describe("assistant broadcast send sender fan-out errors", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("returns a stable assistant error when broadcast sender user is missing", async () => {
    const ctx = createToolContext(
      {
        notificationBroadcast: {
          create: vi.fn().mockResolvedValue({
            id: "broadcast_missing_sender",
            title: "Office update",
            targetType: "user",
          }),
        },
        notification: {
          create: vi.fn().mockRejectedValue({
            code: "P2003",
            message: "Foreign key constraint failed",
            meta: { field_name: "Notification_senderId_fkey" },
          }),
        },
      },
      SystemRole.MANAGER,
    );

    const result = await executeTool(
      "send_broadcast",
      JSON.stringify({
        title: "Office update",
        targetType: "user",
        targetValue: "user_2",
      }),
      ctx,
    );

    expect(JSON.parse(result.content)).toEqual({
      error: "Sender user not found with the given criteria.",
    });
  });

  it("returns a stable assistant error when broadcast fan-out loses sender rows inside the router transaction", async () => {
    const senderMissingTx = {
      notificationBroadcast: {
        create: vi.fn().mockRejectedValue(
          Object.assign(new Error("Foreign key constraint failed"), {
            code: "P2003",
            meta: { field_name: "NotificationBroadcast_senderId_fkey" },
          }),
        ),
        update: vi.fn(),
      },
      notification: {
        create: vi.fn(),
      },
    };
    const senderMissingCtx = createToolContext(
      {
        user: {
          findMany: vi.fn().mockResolvedValue([{ id: "user_2" }]),
        },
        $transaction: vi.fn(async (callback: (db: typeof senderMissingTx) => Promise<unknown>) =>
          callback(senderMissingTx)),
        notificationBroadcast: {
          create: vi.fn(),
          update: vi.fn(),
        },
        notification: {
          create: vi.fn(),
        },
      },
      SystemRole.MANAGER,
    );

    const senderMissingResult = await executeTool(
      "send_broadcast",
      JSON.stringify({
        title: "Office update",
        targetType: "all",
      }),
      senderMissingCtx,
    );

    expect(JSON.parse(senderMissingResult.content)).toEqual({
      error: "Sender user not found with the given criteria.",
    });
  });

  it("returns a stable assistant error when broadcast creation fails because the sender user is missing", async () => {
    const ctx = createToolContext(
      {
        user: {
          findMany: vi.fn().mockResolvedValue([{ id: "user_2" }]),
        },
        notificationBroadcast: {
          create: vi.fn().mockRejectedValue(
            Object.assign(new Error("Foreign key constraint failed"), {
              code: "P2003",
              meta: { field_name: "NotificationBroadcast_senderId_fkey" },
            }),
          ),
        },
      },
      SystemRole.MANAGER,
    );

    const result = await executeTool(
      "send_broadcast",
      JSON.stringify({
        title: "Office update",
        targetType: "all",
      }),
      ctx,
    );

    expect(JSON.parse(result.content)).toEqual({
      error: "Sender user not found with the given criteria.",
    });
  });

  it("returns a stable assistant error when scheduled broadcast creation loses the sender user", async () => {
    const ctx = createToolContext(
      {
        user: {
          findMany: vi.fn().mockResolvedValue([{ id: "user_2" }]),
        },
        notificationBroadcast: {
          create: vi.fn().mockRejectedValue(
            Object.assign(new Error("Foreign key constraint failed"), {
              code: "P2003",
              meta: { field_name: "NotificationBroadcast_senderId_fkey" },
            }),
          ),
        },
        notification: {
          create: vi.fn(),
        },
      },
      SystemRole.MANAGER,
    );

    const result = await executeTool(
      "send_broadcast",
      JSON.stringify({
        title: "Office update",
        targetType: "all",
        scheduledAt: "2099-04-10T08:00:00.000Z",
      }),
      ctx,
    );

    expect(JSON.parse(result.content)).toEqual({
      error: "Sender user not found with the given criteria.",
    });
    expect(ctx.db.notification.create).not.toHaveBeenCalled();
  });
});
