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 {
  useDistributionsQuery,
  useQuotaQuery,
  useCreateDistributionMutation,
} from "@/services/distributions"

import { server } from "../mocks/server"
import { mockDistributionsPage, mockQuotaStatus } 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("useDistributionsQuery", () => {
  it("returns paginated distributions data", async () => {
    const { result } = renderHook(() => useDistributionsQuery(), {
      wrapper: createWrapper(),
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(result.current.data).toEqual(mockDistributionsPage)
    expect(result.current.data?.content).toHaveLength(1)
  })

  it("applies filter params", async () => {
    const { result } = renderHook(
      () =>
        useDistributionsQuery({
          memberId: "m1",
          from: "2025-06-01",
          to: "2025-06-30",
        }),
      { wrapper: createWrapper() }
    )

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(result.current.data?.content).toBeDefined()
  })
})

describe("useQuotaQuery", () => {
  it("returns quota for given member", async () => {
    const { result } = renderHook(() => useQuotaQuery("m1"), {
      wrapper: createWrapper(),
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(result.current.data).toEqual(mockQuotaStatus)
    expect(result.current.data?.monthlyLimitGrams).toBe(50)
    expect(result.current.data?.usedGrams).toBe(15)
  })

  it("is disabled when memberId is empty", async () => {
    const { result } = renderHook(() => useQuotaQuery(""), {
      wrapper: createWrapper(),
    })

    // Should not fetch
    expect(result.current.fetchStatus).toBe("idle")
  })
})

describe("useCreateDistributionMutation", () => {
  it("calls POST and returns new distribution", async () => {
    const { result } = renderHook(() => useCreateDistributionMutation(), {
      wrapper: createWrapper(),
    })

    result.current.mutate({
      memberId: "m1",
      batchId: "b1",
      amountGrams: 5.0,
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(result.current.data?.memberId).toBe("m1")
    expect(result.current.data?.batchId).toBe("b1")
  })
})
