import { beforeEach, describe, expect, it } from "vitest";
import { events, ticketTypes, tickets } from "../drizzle/schema";
import { appRouter } from "./routers";
import { getTicketByToken, setDbForTests } from "./db";
import type { TrpcContext } from "./_core/context";

function createTicketDb(empty = false) {
  const ticket = { id: 21, orderId: 9, eventId: 7, ticketTypeId: 8, attendeeName: "Ama Mensah", attendeeEmail: "ama@example.com", qrToken: "GNG-ABCDEFGH", status: "valid", issuedAt: new Date() };
  const event = { id: 7, title: "Night Market", location: "Accra", startsAt: new Date("2026-09-01T18:00:00Z") };
  const ticketType = { id: 8, name: "General admission" };
  return {
    select: () => ({
      from: (table: unknown) => ({
        where: () => ({ limit: async () => empty ? [] : table === tickets ? [ticket] : table === events ? [event] : table === ticketTypes ? [ticketType] : [], }),
      }),
    }),
    ticket,
    event,
    ticketType,
  };
}

const caller = () => appRouter.createCaller({ user: null, req: {} as TrpcContext["req"], res: {} as TrpcContext["res"] });

describe("public ticket-link access", () => {
  beforeEach(() => setDbForTests(null));

  it("returns the ticket, event, and ticket type for a valid QR token", async () => {
    const db = createTicketDb();
    setDbForTests(db as never);
    await expect(getTicketByToken("GNG-ABCDEFGH")).resolves.toMatchObject({ ticket: db.ticket, event: db.event, ticketType: db.ticketType });
  });

  it("exposes valid token lookup through the public tickets.byToken procedure", async () => {
    const db = createTicketDb();
    setDbForTests(db as never);
    await expect(caller().tickets.byToken({ token: "GNG-ABCDEFGH" })).resolves.toMatchObject({ ticket: db.ticket, event: db.event, ticketType: db.ticketType });
  });

  it("returns an empty result for an invalid token without leaking ticket data", async () => {
    const db = createTicketDb(true);
    setDbForTests(db as never);
    await expect(caller().tickets.byToken({ token: "GNG-ZZZZZZZZ" })).resolves.toBeUndefined();
  });
});

