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

const mutationMock = vi.fn()
const deleteManyMock = vi.fn()
const assertAuthenticatedSession = vi.fn()

vi.mock("convex/browser", () => ({
  ConvexHttpClient: vi.fn().mockImplementation(() => ({
    mutation: mutationMock,
  })),
}))

vi.mock("@/lib/prisma", () => ({
  prisma: {
    authUser: {
      deleteMany: deleteManyMock,
    },
  },
}))

vi.mock("@/lib/auth-server", () => ({
  assertAuthenticatedSession: assertAuthenticatedSession,
}))

describe("POST /api/admin/machines/delete", () => {
  const originalEnv = process.env.NEXT_PUBLIC_CONVEX_URL

  let restoreConsole: (() => void) | undefined

  beforeEach(() => {
    process.env.NEXT_PUBLIC_CONVEX_URL = "https://convex.example"
    mutationMock.mockReset()
    deleteManyMock.mockReset()
    assertAuthenticatedSession.mockReset()
    assertAuthenticatedSession.mockResolvedValue({
      user: {
        email: "admin@example.com",
        name: "Admin",
        role: "ADMIN",
        tenantId: "tenant-1",
        avatarUrl: null,
      },
    })
    mutationMock.mockResolvedValueOnce({ _id: "user_123" })
    const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {})
    restoreConsole = () => consoleSpy.mockRestore()
  })

  afterEach(() => {
    process.env.NEXT_PUBLIC_CONVEX_URL = originalEnv
    restoreConsole?.()
  })

  it("returns ok when the machine removal succeeds", async () => {
    mutationMock.mockResolvedValueOnce({ ok: true })
    const { POST } = await import("./route")
    const response = await POST(
      new Request("http://localhost/api/admin/machines/delete", {
        method: "POST",
        body: JSON.stringify({ machineId: "jn_machine" }),
      })
    )

    expect(response.status).toBe(200)
    await expect(response.json()).resolves.toEqual({ ok: true, machineMissing: false })
    expect(deleteManyMock).toHaveBeenCalledWith({ where: { email: "machine-jn_machine@machines.local" } })
    expect(mutationMock).toHaveBeenNthCalledWith(1, expect.anything(), expect.objectContaining({ email: "admin@example.com" }))
    expect(mutationMock).toHaveBeenNthCalledWith(2, expect.anything(), expect.objectContaining({ machineId: "jn_machine" }))
  })

  it("still succeeds when the Convex machine is already missing", async () => {
    mutationMock.mockRejectedValueOnce(new Error("Máquina não encontrada"))
    const { POST } = await import("./route")
    const response = await POST(
      new Request("http://localhost/api/admin/machines/delete", {
        method: "POST",
        body: JSON.stringify({ machineId: "jn_machine" }),
      })
    )

    expect(response.status).toBe(200)
    await expect(response.json()).resolves.toEqual({ ok: true, machineMissing: true })
    expect(deleteManyMock).toHaveBeenCalledWith({ where: { email: "machine-jn_machine@machines.local" } })
  })

  it("returns an error for other Convex failures", async () => {
    mutationMock.mockRejectedValueOnce(new Error("timeout error"))
    const { POST } = await import("./route")
    const response = await POST(
      new Request("http://localhost/api/admin/machines/delete", {
        method: "POST",
        body: JSON.stringify({ machineId: "jn_machine" }),
      })
    )

    expect(response.status).toBe(500)
    await expect(response.json()).resolves.toEqual({ error: "Falha ao remover máquina no Convex" })
    expect(deleteManyMock).not.toHaveBeenCalled()
  })
})
