import { convexTest } from "convex-test";
import { describe, it, expect } from "vitest";
import { api } from "./_generated/api";
import schema from "./schema";

const modules = import.meta.glob("./**/*.ts");

async function setupAdminUser(t: ReturnType<typeof convexTest>) {
  const asAdmin = t.withIdentity({
    name: "Admin",
    email: "admin@example.com",
    subject: "clerk_admin_123",
  });
  const userId = await asAdmin.mutation(api.users.store, {});
  await t.run(async (ctx) => {
    await ctx.db.patch(userId, { role: "admin" });
  });
  return asAdmin;
}

describe("categories", () => {
  it("list returns all categories ordered by name", async () => {
    const t = convexTest(schema, modules);
    const asAdmin = await setupAdminUser(t);

    await asAdmin.mutation(api.categories.create, {
      name: "Zebra",
      slug: "zebra",
    });
    await asAdmin.mutation(api.categories.create, {
      name: "Alpha",
      slug: "alpha",
    });

    const list = await t.query(api.categories.list, {});
    expect(list).toHaveLength(2);
    expect(list[0].name).toBe("Alpha");
    expect(list[1].name).toBe("Zebra");
  });

  it("list with parentId returns only children of that parent", async () => {
    const t = convexTest(schema, modules);
    const asAdmin = await setupAdminUser(t);

    const parentId = await asAdmin.mutation(api.categories.create, {
      name: "Parent",
      slug: "parent",
    });
    await asAdmin.mutation(api.categories.create, {
      name: "Child A",
      slug: "child-a",
      parentId,
    });
    await asAdmin.mutation(api.categories.create, {
      name: "Child B",
      slug: "child-b",
      parentId,
    });
    await asAdmin.mutation(api.categories.create, {
      name: "Other",
      slug: "other",
    });

    const children = await t.query(api.categories.list, { parentId });
    expect(children).toHaveLength(2);
    expect(children.map((c) => c.name).sort()).toEqual(["Child A", "Child B"]);
  });

  it("getBySlug returns category when slug exists", async () => {
    const t = convexTest(schema, modules);
    const asAdmin = await setupAdminUser(t);

    await asAdmin.mutation(api.categories.create, {
      name: "Pet Food",
      slug: "pet-food",
    });

    const category = await t.query(api.categories.getBySlug, {
      slug: "pet-food",
    });
    expect(category).not.toBeNull();
    expect(category?.name).toBe("Pet Food");
    expect(category?.slug).toBe("pet-food");
  });

  it("getBySlug returns null for unknown slug", async () => {
    const t = convexTest(schema, modules);
    const category = await t.query(api.categories.getBySlug, {
      slug: "does-not-exist",
    });
    expect(category).toBeNull();
  });

  it("create succeeds for admin users", async () => {
    const t = convexTest(schema, modules);
    const asAdmin = await setupAdminUser(t);

    const id = await asAdmin.mutation(api.categories.create, {
      name: "Toys",
      slug: "toys",
    });
    expect(id).toBeTruthy();

    const category = await t.query(api.categories.getBySlug, { slug: "toys" });
    expect(category?.name).toBe("Toys");
  });

  it("create throws for non-admin users", async () => {
    const t = convexTest(schema, modules);
    const asCustomer = t.withIdentity({
      name: "Customer",
      email: "customer@example.com",
      subject: "clerk_customer_123",
    });
    await asCustomer.mutation(api.users.store, {});

    await expect(
      asCustomer.mutation(api.categories.create, {
        name: "Illegal",
        slug: "illegal",
      }),
    ).rejects.toThrow("Unauthorized: admin access required");
  });
});
