import { describe, it, expect, beforeEach, vi } from "vitest";

vi.mock("@/lib/db", () => ({
  db: {
    user: {
      findUnique: vi.fn(),
      update: 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";
import { db } from "@/lib/db";

describe("GET /api/marketplace/terms", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("returns 401 when not authenticated", async () => {
    vi.mocked(auth).mockResolvedValue(null as never);

    const { GET } = await import("@/app/api/marketplace/terms/route");
    const response = await GET();

    expect(response.status).toBe(401);
    const data = await response.json();
    expect(data.error).toBe("Unauthorized");
  });

  it("returns accepted=false when terms not yet accepted", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    vi.mocked(db.user.findUnique).mockResolvedValue({
      marketplaceTermsAcceptedAt: null,
    } as never);

    const { GET } = await import("@/app/api/marketplace/terms/route");
    const response = await GET();
    const data = await response.json();

    expect(response.status).toBe(200);
    expect(data.accepted).toBe(false);
    expect(data.acceptedAt).toBeNull();
    expect(db.user.findUnique).toHaveBeenCalledWith({
      where: { id: "user-1" },
      select: { marketplaceTermsAcceptedAt: true },
    });
  });

  it("returns accepted=true with timestamp when terms accepted", async () => {
    const acceptedDate = new Date("2026-02-20T12:00:00.000Z");
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    vi.mocked(db.user.findUnique).mockResolvedValue({
      marketplaceTermsAcceptedAt: acceptedDate,
    } as never);

    const { GET } = await import("@/app/api/marketplace/terms/route");
    const response = await GET();
    const data = await response.json();

    expect(response.status).toBe(200);
    expect(data.accepted).toBe(true);
    expect(data.acceptedAt).toBe("2026-02-20T12:00:00.000Z");
  });

  it("returns accepted=false when user not found", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    vi.mocked(db.user.findUnique).mockResolvedValue(null);

    const { GET } = await import("@/app/api/marketplace/terms/route");
    const response = await GET();
    const data = await response.json();

    expect(response.status).toBe(200);
    expect(data.accepted).toBe(false);
    expect(data.acceptedAt).toBeNull();
  });

  it("returns 500 on db error", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    vi.mocked(db.user.findUnique).mockRejectedValue(new Error("DB down"));

    const { GET } = await import("@/app/api/marketplace/terms/route");
    const response = await GET();

    expect(response.status).toBe(500);
    const data = await response.json();
    expect(data.error).toBe("Internal error");
  });
});

describe("POST /api/marketplace/terms", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("returns 401 when not authenticated", async () => {
    vi.mocked(auth).mockResolvedValue(null as never);

    const { POST } = await import("@/app/api/marketplace/terms/route");
    const response = await POST();

    expect(response.status).toBe(401);
    const data = await response.json();
    expect(data.error).toBe("Unauthorized");
  });

  it("sets marketplaceTermsAcceptedAt and returns accepted=true", async () => {
    const now = new Date("2026-03-01T10:00:00.000Z");
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    vi.mocked(db.user.update).mockResolvedValue({
      marketplaceTermsAcceptedAt: now,
    } as never);

    const { POST } = await import("@/app/api/marketplace/terms/route");
    const response = await POST();
    const data = await response.json();

    expect(response.status).toBe(200);
    expect(data.accepted).toBe(true);
    expect(data.acceptedAt).toBe("2026-03-01T10:00:00.000Z");
    expect(db.user.update).toHaveBeenCalledWith({
      where: { id: "user-1" },
      data: { marketplaceTermsAcceptedAt: expect.any(Date) },
      select: { marketplaceTermsAcceptedAt: true },
    });
  });

  it("overwrites existing acceptance timestamp", async () => {
    const newDate = new Date("2026-03-01T15:00:00.000Z");
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    vi.mocked(db.user.update).mockResolvedValue({
      marketplaceTermsAcceptedAt: newDate,
    } as never);

    const { POST } = await import("@/app/api/marketplace/terms/route");
    const response = await POST();
    const data = await response.json();

    expect(response.status).toBe(200);
    expect(data.accepted).toBe(true);
    expect(data.acceptedAt).toBe("2026-03-01T15:00:00.000Z");
  });

  it("returns 500 on db error", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    vi.mocked(db.user.update).mockRejectedValue(new Error("DB down"));

    const { POST } = await import("@/app/api/marketplace/terms/route");
    const response = await POST();

    expect(response.status).toBe(500);
    const data = await response.json();
    expect(data.error).toBe("Internal error");
  });
});
