import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { listProductTypes } from '../../../features/product-types/api/listProductTypes'
import { getProductTypeById } from '../../../features/product-types/api/getProductTypeById'
import { createProductType } from '../../../features/product-types/api/createProductType'
import { updateProductType } from '../../../features/product-types/api/updateProductType'
import { deactivateProductType } from '../../../features/product-types/api/deactivateProductType'
import type { ProductTypeListItem, ProductTypeDetail, PagedResult } from '../../../features/product-types/types'

const API_URL = 'http://localhost:5000'

const mockListItem: ProductTypeListItem = {
  id: 1,
  nombre: 'Avisos Clasificados',
  hasDuration: true,
  requiresText: true,
  requiresCategory: true,
  isBundle: false,
  allowImages: true,
  isActive: true,
}

const mockDetail: ProductTypeDetail = {
  id: 1,
  nombre: 'Avisos Clasificados',
  hasDuration: true,
  requiresText: true,
  requiresCategory: true,
  isBundle: false,
  allowImages: true,
  maxImages: 5,
  maxImageSizeMB: 2.5,
  maxImageWidth: 800,
  maxImageHeight: 600,
  isActive: true,
  fechaCreacion: '2026-04-19T00:00:00Z',
  fechaModificacion: null,
}

const mockPaged: PagedResult<ProductTypeListItem> = {
  items: [mockListItem],
  page: 1,
  pageSize: 20,
  total: 1,
}

const server = setupServer()

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

describe('listProductTypes', () => {
  it('calls GET /api/v1/product-types and returns paged result', async () => {
    server.use(
      http.get(`${API_URL}/api/v1/product-types`, () => HttpResponse.json(mockPaged)),
    )
    const result = await listProductTypes()
    expect(result).toEqual(mockPaged)
  })

  it('passes query params when provided', async () => {
    let capturedUrl = ''
    server.use(
      http.get(`${API_URL}/api/v1/product-types`, ({ request }) => {
        capturedUrl = request.url
        return HttpResponse.json(mockPaged)
      }),
    )
    await listProductTypes({ page: 2, pageSize: 10, activo: true, search: 'test' })
    expect(capturedUrl).toContain('page=2')
    expect(capturedUrl).toContain('pageSize=10')
    expect(capturedUrl).toContain('search=test')
  })
})

describe('getProductTypeById', () => {
  it('calls GET /api/v1/product-types/:id and returns detail', async () => {
    server.use(
      http.get(`${API_URL}/api/v1/product-types/1`, () => HttpResponse.json(mockDetail)),
    )
    const result = await getProductTypeById(1)
    expect(result).toEqual(mockDetail)
  })
})

describe('createProductType', () => {
  it('calls POST /api/v1/admin/product-types with payload', async () => {
    let capturedBody: unknown = null
    server.use(
      http.post(`${API_URL}/api/v1/admin/product-types`, async ({ request }) => {
        capturedBody = await request.json()
        return HttpResponse.json(mockDetail, { status: 201 })
      }),
    )
    const req = {
      nombre: 'Avisos Clasificados',
      hasDuration: true,
      requiresText: true,
      requiresCategory: false,
      isBundle: false,
      allowImages: true,
    }
    await createProductType(req)
    expect(capturedBody).toEqual(req)
  })
})

describe('updateProductType', () => {
  it('calls PUT /api/v1/admin/product-types/:id with payload', async () => {
    let capturedBody: unknown = null
    server.use(
      http.put(`${API_URL}/api/v1/admin/product-types/1`, async ({ request }) => {
        capturedBody = await request.json()
        return HttpResponse.json(mockDetail)
      }),
    )
    const req = { nombre: 'Modificado', hasDuration: false, requiresText: false, requiresCategory: false, isBundle: false, allowImages: false }
    await updateProductType(1, req)
    expect(capturedBody).toEqual(req)
  })
})

describe('deactivateProductType', () => {
  it('calls DELETE /api/v1/admin/product-types/:id', async () => {
    let called = false
    server.use(
      http.delete(`${API_URL}/api/v1/admin/product-types/1`, () => {
        called = true
        return new HttpResponse(null, { status: 204 })
      }),
    )
    await deactivateProductType(1)
    expect(called).toBe(true)
  })
})
