import { describe, it, expect, beforeEach, vi } from "vitest";
import { GET, POST } from "@/app/api/team/route";
import { db } from "@/lib/db";

vi.mock("@/lib/db", () => ({
  db: {
    user: { findUnique: vi.fn(), update: vi.fn(), findFirst: vi.fn(), count: vi.fn() },
    team: { findUnique: vi.fn(), create: vi.fn() },
    teamInvite: { findFirst: vi.fn(), findUnique: vi.fn(), create: vi.fn(), delete: vi.fn() },
    $transaction: vi.fn(),
  },
}));

vi.mock("@/lib/auth", () => ({ auth: vi.fn() }));
vi.mock("@/lib/logger", () => ({
  logger: { info: vi.fn(), error: vi.fn(), warn: vi.fn() },
}));

import { auth } from "@/lib/auth";

describe("/api/team - GET", () => {
  beforeEach(() => vi.clearAllMocks());

  it("returns 401 when not authenticated", async () => {
    vi.mocked(auth).mockResolvedValue(null as any);
    const res = await GET();
    expect(res.status).toBe(401);
  });

  it("returns null team when user has no team", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "u1" } } as any);
    vi.mocked(db.user.findUnique).mockResolvedValue({ teamId: null, teamRole: null } as any);

    const res = await GET();
    const data = await res.json();
    expect(res.status).toBe(200);
    expect(data.team).toBeNull();
  });

  it("returns team with members and invites", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "u1" } } as any);
    vi.mocked(db.user.findUnique).mockResolvedValue({ teamId: "t1", teamRole: "admin" } as any);

    const mockTeam = {
      id: "t1",
      name: "Test Team",
      owner: { id: "u1", name: "Admin", email: "admin@test.com" },
      members: [{ id: "u1", name: "Admin", email: "admin@test.com", teamRole: "admin", createdAt: "2026-01-01" }],
      invites: [],
    };
    vi.mocked(db.team.findUnique).mockResolvedValue(mockTeam as any);

    const res = await GET();
    const data = await res.json();
    expect(res.status).toBe(200);
    expect(data.team.name).toBe("Test Team");
    expect(data.userRole).toBe("admin");
  });
});

describe("/api/team - POST (create)", () => {
  beforeEach(() => vi.clearAllMocks());

  it("returns 401 when not authenticated", async () => {
    vi.mocked(auth).mockResolvedValue(null as any);
    const req = new Request("http://localhost/api/team", {
      method: "POST",
      body: JSON.stringify({ name: "Test" }),
    });
    const res = await POST(req);
    expect(res.status).toBe(401);
  });

  it("returns 400 when name is empty", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "u1" } } as any);
    const req = new Request("http://localhost/api/team", {
      method: "POST",
      body: JSON.stringify({ name: "" }),
    });
    const res = await POST(req);
    expect(res.status).toBe(400);
  });

  it("returns 403 when user is not on team plan", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "u1" } } as any);
    vi.mocked(db.user.findUnique).mockResolvedValue({ id: "u1", plan: "pro", teamId: null } as any);

    const req = new Request("http://localhost/api/team", {
      method: "POST",
      body: JSON.stringify({ name: "My Team" }),
    });
    const res = await POST(req);
    expect(res.status).toBe(403);
  });

  it("returns 409 when user already in a team", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "u1" } } as any);
    vi.mocked(db.user.findUnique).mockResolvedValue({ id: "u1", plan: "team", teamId: "t1" } as any);

    const req = new Request("http://localhost/api/team", {
      method: "POST",
      body: JSON.stringify({ name: "My Team" }),
    });
    const res = await POST(req);
    expect(res.status).toBe(409);
  });

  it("creates team successfully for team plan user", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "u1" } } as any);
    vi.mocked(db.user.findUnique).mockResolvedValue({ id: "u1", plan: "team", teamId: null } as any);
    vi.mocked(db.team.create).mockResolvedValue({ id: "t1", name: "My Team", ownerId: "u1" } as any);
    vi.mocked(db.user.update).mockResolvedValue({} as any);

    const req = new Request("http://localhost/api/team", {
      method: "POST",
      body: JSON.stringify({ name: "My Team" }),
    });
    const res = await POST(req);
    const data = await res.json();

    expect(res.status).toBe(201);
    expect(data.team.name).toBe("My Team");
    expect(db.team.create).toHaveBeenCalledWith(
      expect.objectContaining({
        data: expect.objectContaining({ name: "My Team", ownerId: "u1" }),
      }),
    );
  });
});
