import { describe, expect, it, beforeEach, vi } from "vitest";
import { appRouter } from "./routers";
import type { TrpcContext } from "./_core/context";

// Mock the database and notification functions
vi.mock("./db", () => ({
  createLead: vi.fn(async (lead) => ({
    id: 1,
    ...lead,
    createdAt: new Date(),
  })),
}));

vi.mock("./_core/notification", () => ({
  notifyOwner: vi.fn(async () => true),
}));

function createPublicContext(): TrpcContext {
  return {
    user: null,
    req: {
      protocol: "https",
      headers: {},
    } as TrpcContext["req"],
    res: {
      clearCookie: vi.fn(),
    } as unknown as TrpcContext["res"],
  };
}

describe("leads.submit", () => {
  let caller: ReturnType<typeof appRouter.createCaller>;

  beforeEach(() => {
    const ctx = createPublicContext();
    caller = appRouter.createCaller(ctx);
  });

  it("submits a lead with all required fields", async () => {
    const result = await caller.leads.submit({
      name: "John Doe",
      email: "john@example.com",
      phone: "647-983-0755",
      company: "Acme Corp",
      serviceInterest: "Marketing",
      message: "Interested in marketing services",
    });

    expect(result).toBeDefined();
    expect(result.name).toBe("John Doe");
    expect(result.email).toBe("john@example.com");
    expect(result.serviceInterest).toBe("Marketing");
  });

  it("submits a lead with only required fields", async () => {
    const result = await caller.leads.submit({
      name: "Jane Smith",
      email: "jane@example.com",
      serviceInterest: "Staffing",
    });

    expect(result).toBeDefined();
    expect(result.name).toBe("Jane Smith");
    expect(result.email).toBe("jane@example.com");
    expect(result.serviceInterest).toBe("Staffing");
  });

  it("rejects invalid email", async () => {
    try {
      await caller.leads.submit({
        name: "Invalid User",
        email: "not-an-email",
        serviceInterest: "Financial Consultation",
      });
      expect.fail("Should have thrown an error");
    } catch (error: any) {
      expect(error.message).toContain("email");
    }
  });

  it("rejects empty name", async () => {
    try {
      await caller.leads.submit({
        name: "",
        email: "test@example.com",
        serviceInterest: "Marketing",
      });
      expect.fail("Should have thrown an error");
    } catch (error: any) {
      expect(error.message).toContain("Name");
    }
  });

  it("rejects invalid service interest", async () => {
    try {
      await caller.leads.submit({
        name: "Test User",
        email: "test@example.com",
        serviceInterest: "InvalidService" as any,
      });
      expect.fail("Should have thrown an error");
    } catch (error: any) {
      expect(error.message).toBeDefined();
    }
  });

  it("accepts all three valid service interests", async () => {
    const services = ["Marketing", "Staffing", "Financial Consultation"] as const;

    for (const service of services) {
      const result = await caller.leads.submit({
        name: "Test User",
        email: "test@example.com",
        serviceInterest: service,
      });

      expect(result.serviceInterest).toBe(service);
    }
  });

  it("handles optional fields correctly", async () => {
    const result = await caller.leads.submit({
      name: "Minimal User",
      email: "minimal@example.com",
      serviceInterest: "Marketing",
      phone: undefined,
      company: undefined,
      message: undefined,
    });

    expect(result).toBeDefined();
    expect(result.name).toBe("Minimal User");
  });
});
