import { renderHook, waitFor } from "@testing-library/react"
import { afterAll, afterEach, beforeAll, describe, expect, it } from "vitest"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import React from "react"

import {
  useStaffListQuery,
  useInviteStaffMutation,
  useUpdateStaffPermissionsMutation,
  useRevokeStaffMutation,
} from "@/services/staff"

import { server } from "../mocks/server"
import { mockStaffList } from "../mocks/handlers"

beforeAll(() => server.listen({ onUnhandledRequest: "error" }))
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

function createWrapper() {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false, gcTime: 0 } },
  })
  return function Wrapper({ children }: { children: React.ReactNode }) {
    return (
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    )
  }
}

describe("useStaffListQuery", () => {
  it("returns staff accounts list", async () => {
    const { result } = renderHook(() => useStaffListQuery(), {
      wrapper: createWrapper(),
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(result.current.data).toEqual(mockStaffList)
    expect(result.current.data).toHaveLength(2)
    expect(result.current.data?.[0].role).toBe("ADMIN")
    expect(result.current.data?.[1].role).toBe("STAFF")
  })

  it("returns error state on API failure", async () => {
    const { http, HttpResponse } = await import("msw")
    server.use(
      http.get("/api/backend/staff", () => {
        return HttpResponse.json(
          { code: "UNAUTHORIZED", message: "Not authenticated" },
          { status: 401 }
        )
      })
    )

    const { result } = renderHook(() => useStaffListQuery(), {
      wrapper: createWrapper(),
    })

    await waitFor(() => expect(result.current.isError).toBe(true))
  })
})

describe("useInviteStaffMutation", () => {
  it("calls POST with email and permissions", async () => {
    const { result } = renderHook(() => useInviteStaffMutation(), {
      wrapper: createWrapper(),
    })

    result.current.mutate({
      email: "newstaff@club.de",
      displayName: "New Staff",
      role: "STAFF",
      permissions: ["MANAGE_DISTRIBUTIONS"],
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(result.current.data?.email).toBe("newstaff@club.de")
    expect(result.current.data?.status).toBe("INVITED")
  })
})

describe("useUpdateStaffPermissionsMutation", () => {
  it("calls PUT with updated permissions", async () => {
    const { result } = renderHook(
      () => useUpdateStaffPermissionsMutation("s2"),
      { wrapper: createWrapper() }
    )

    result.current.mutate({
      role: "MANAGER",
      permissions: ["MANAGE_MEMBERS", "MANAGE_DISTRIBUTIONS"],
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(result.current.data?.role).toBe("MANAGER")
  })
})

describe("useRevokeStaffMutation", () => {
  it("calls POST revoke endpoint", async () => {
    const { result } = renderHook(() => useRevokeStaffMutation(), {
      wrapper: createWrapper(),
    })

    result.current.mutate("s2")

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
  })
})
