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

type AuthenticatedUser = NonNullable<TrpcContext["user"]>;

function createAdminContext(): { ctx: TrpcContext } {
  const user: AuthenticatedUser = {
    id: 1,
    openId: "admin-user",
    email: "admin@example.com",
    name: "Admin User",
    loginMethod: "manus",
    role: "admin",
    createdAt: new Date(),
    updatedAt: new Date(),
    lastSignedIn: new Date(),
  };

  const ctx: TrpcContext = {
    user,
    req: {
      protocol: "https",
      headers: {},
    } as TrpcContext["req"],
    res: {
      clearCookie: () => {},
    } as TrpcContext["res"],
  };

  return { ctx };
}

function createPublicContext(): { ctx: TrpcContext } {
  const ctx: TrpcContext = {
    user: null,
    req: {
      protocol: "https",
      headers: {},
    } as TrpcContext["req"],
    res: {
      clearCookie: () => {},
    } as TrpcContext["res"],
  };

  return { ctx };
}

describe("applications", () => {
  it("should allow public users to create applications", async () => {
    const { ctx } = createPublicContext();
    const caller = appRouter.createCaller(ctx);

    const result = await caller.applications.create({
      jobId: 1,
      fullName: "João Silva",
      phone: "(11) 99999-9999",
      rgFrontUrl: "https://example.com/rg-front.jpg",
      rgBackUrl: "https://example.com/rg-back.jpg",
    });

    expect(result).toBeDefined();
  });

  it("should allow admin users to list applications", async () => {
    const { ctx } = createAdminContext();
    const caller = appRouter.createCaller(ctx);

    const result = await caller.applications.list({});

    expect(Array.isArray(result)).toBe(true);
  });

  it("should deny non-admin users from listing applications", async () => {
    const { ctx } = createPublicContext();
    const caller = appRouter.createCaller(ctx);

    try {
      await caller.applications.list({});
      expect.fail("Should have thrown an error");
    } catch (error) {
      expect(error).toBeDefined();
    }
  });

  it("should allow admin users to update application status", async () => {
    const { ctx } = createAdminContext();
    const caller = appRouter.createCaller(ctx);

    // First create an application
    const publicCaller = appRouter.createCaller(createPublicContext().ctx);
    await publicCaller.applications.create({
      jobId: 1,
      fullName: "Maria Santos",
      phone: "(21) 98888-8888",
      rgFrontUrl: "https://example.com/rg-front.jpg",
      rgBackUrl: "https://example.com/rg-back.jpg",
    });

    // Then update its status
    const result = await caller.applications.updateStatus({
      id: 1,
      status: "approved",
      notes: "Candidato aprovado",
    });

    expect(result).toBeDefined();
  });

  it("should deny non-admin users from updating application status", async () => {
    const { ctx } = createPublicContext();
    const caller = appRouter.createCaller(ctx);

    try {
      await caller.applications.updateStatus({
        id: 1,
        status: "approved",
      });
      expect.fail("Should have thrown an error");
    } catch (error) {
      expect(error).toBeDefined();
    }
  });
});

describe("jobs", () => {
  it("should allow public users to list jobs", async () => {
    const { ctx } = createPublicContext();
    const caller = appRouter.createCaller(ctx);

    const result = await caller.jobs.list();

    expect(Array.isArray(result)).toBe(true);
  });
});
