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 {
  useBatchesQuery,
  useCreateBatchMutation,
  useRecallBatchMutation,
  useStrainsQuery,
} from "@/services/stock"

import { server } from "../mocks/server"
import { mockBatchesPage } 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("useBatchesQuery", () => {
  it("returns paginated batches", async () => {
    const { result } = renderHook(() => useBatchesQuery(), {
      wrapper: createWrapper(),
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(result.current.data).toEqual(mockBatchesPage)
    expect(result.current.data?.content[0].strainName).toBe("Northern Lights")
  })

  it("accepts status filter", async () => {
    const { result } = renderHook(
      () => useBatchesQuery({ status: "AVAILABLE" }),
      { wrapper: createWrapper() }
    )

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

describe("useStrainsQuery", () => {
  it("returns strain list", async () => {
    const { result } = renderHook(() => useStrainsQuery(), {
      wrapper: createWrapper(),
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(result.current.data).toHaveLength(2)
    expect(result.current.data?.[0].name).toBe("Northern Lights")
  })
})

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

    result.current.mutate({
      strainName: "Blue Dream",
      thcPercent: 21.0,
      cbdPercent: 0.1,
      totalGrams: 300,
      supplier: "Test Supplier",
      harvestDate: "2025-06-01",
    })

    await waitFor(() => expect(result.current.isSuccess).toBe(true))
    expect(result.current.data?.strainName).toBe("Blue Dream")
    expect(result.current.data?.status).toBe("AVAILABLE")
  })
})

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

    result.current.mutate("b1")

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