import { createKyselyMock } from "@tailor-platform/sdk/vitest";
import { describe, expect, it } from "vitest";
import type { Namespace } from "../generated/kysely-tailordb";
import { baseTemplate, baseEmailTemplate } from "../testing/fixtures";
import { run } from "./listNotificationTemplates";

describe("listNotificationTemplates", () => {
  it("returns every template when no filter is supplied", async () => {
    const mock = createKyselyMock<Namespace[keyof Namespace]>();
    mock.enqueueResults([{ ...baseTemplate }, { ...baseEmailTemplate }]);

    const result = await run(mock.db, {});

    expect(result.ok).toBe(true);
    if (result.ok) {
      expect(result.value.items).toHaveLength(2);
    }
  });

  it("filters by eventType when provided", async () => {
    const mock = createKyselyMock<Namespace[keyof Namespace]>();
    mock.enqueueResults([{ ...baseTemplate }]);

    const result = await run(mock.db, { eventType: "PO_ISSUED" });

    expect(result.ok).toBe(true);
    if (result.ok) {
      expect(result.value.items).toHaveLength(1);
      expect(result.value.items[0].eventType).toBe("PO_ISSUED");
    }
  });

  it("filters by channelId when provided", async () => {
    const mock = createKyselyMock<Namespace[keyof Namespace]>();
    mock.enqueueResults([{ ...baseTemplate }]);

    const result = await run(mock.db, { channelId: "channel-1" });

    expect(result.ok).toBe(true);
    if (result.ok) {
      expect(result.value.items).toHaveLength(1);
      expect(result.value.items[0].channelId).toBe("channel-1");
    }
  });

  it("filters by locale when provided", async () => {
    const mock = createKyselyMock<Namespace[keyof Namespace]>();
    mock.enqueueResults([{ ...baseTemplate }]);

    const result = await run(mock.db, { locale: "en-US" });

    expect(result.ok).toBe(true);
    if (result.ok) {
      expect(result.value.items).toHaveLength(1);
      expect(result.value.items[0].locale).toBe("en-US");
    }
  });

  it("combines multiple filters with AND logic", async () => {
    const mock = createKyselyMock<Namespace[keyof Namespace]>();
    mock.enqueueResults([{ ...baseTemplate }]);

    const result = await run(mock.db, {
      eventType: "PO_ISSUED",
      channelId: "channel-1",
      locale: "en-US",
    });

    expect(result.ok).toBe(true);
    if (result.ok) {
      expect(result.value.items).toHaveLength(1);
    }
  });

  it("returns an empty list when no rows match", async () => {
    const mock = createKyselyMock<Namespace[keyof Namespace]>();
    mock.enqueueResults([]);

    const result = await run(mock.db, { locale: "fr-FR" });

    expect(result.ok).toBe(true);
    if (result.ok) {
      expect(result.value.items).toHaveLength(0);
    }
  });

  it("returns rows for every locale variant of a given (eventType, channelId) when only those two filters are supplied", async () => {
    const mock = createKyselyMock<Namespace[keyof Namespace]>();
    mock.enqueueResults([
      { ...baseTemplate, locale: "en-US" },
      { ...baseTemplate, id: "template-ja", locale: "ja-JP" },
    ]);

    const result = await run(mock.db, { eventType: "PO_ISSUED", channelId: "channel-1" });

    expect(result.ok).toBe(true);
    if (result.ok) {
      expect(result.value.items).toHaveLength(2);
      expect(result.value.items.map((t) => t.locale)).toEqual(["en-US", "ja-JP"]);
    }
  });
});
