import { afterEach, describe, expect, it, vi } from "vitest";
import { events, orders, ticketTypes, tickets } from "../drizzle/schema";
import { resendTicketEmail, setDbForTests } from "./db";

const order = { id: 60001, buyerId: 1, buyerEmail: "couragesewor76@gmail.com", buyerName: "Attendee", eventId: 7, ticketTypeId: 8, quantity: 1, totalMinor: 100, status: "paid" as const };
const event = { id: 7, title: "GNG Night", startsAt: new Date("2026-08-29T23:00:00Z"), location: "G+ Nightclub" };
const ticketType = { id: 8, name: "General admission" };
const issuedTicket = { id: 60008, orderId: 60001, qrToken: "gng_existing_ticket", issuedAt: new Date() };

function makeDb(foundOrder: typeof order | undefined) {
  const statuses: string[] = [];
  const db = {
    statuses,
    select() {
      return {
        from(table: unknown) {
          const value = table === orders ? foundOrder : table === events ? event : table === ticketTypes ? ticketType : [issuedTicket];
          return {
            where() {
              return table === tickets
                ? { orderBy: async () => value }
                : { limit: async () => (value ? [value] : []) };
            },
          };
        },
      };
    },
    update() {
      return { set(values: { emailStatus?: string }) { if (values.emailStatus) statuses.push(values.emailStatus); return { where: async () => undefined }; } };
    },
  };
  return db;
}

afterEach(() => setDbForTests(null));

describe("resendTicketEmail", () => {
  it("resends an existing issued order and persists failed delivery status safely", async () => {
    const db = makeDb(order);
    setDbForTests(db as never);
    const sender = vi.fn().mockResolvedValue(false);

    await expect(resendTicketEmail(order.id, 1, "dzidsew@gmail.com", sender)).resolves.toEqual({ sent: false, emailStatus: "failed" });
    expect(sender).toHaveBeenCalledOnce();
    expect(db.statuses).toEqual(["sending", "failed"]);
  });

  it("does not allow a different account to resend the order", async () => {
    setDbForTests(makeDb(undefined) as never);
    await expect(resendTicketEmail(order.id, 99, "other@example.com", vi.fn())).rejects.toThrow("not authorized");
  });
});
