import { describe, it, expect, beforeEach } from 'vitest'
import { http, HttpResponse } from 'msw'
import { server } from '@/test/mocks/server'
import { mockDisclosureRequest, mockDisclosureApproved } from '@/test/mocks/data'
import {
  requestDisclosure,
  getDisclosureRequests,
  getDisclosureCount,
  reviewDisclosure,
} from '@/services/disclosureService'

describe('disclosureService', () => {
  beforeEach(() => {
    localStorage.clear()
    localStorage.setItem('access_token', 'valid-token')
  })

  // ---------- requestDisclosure ----------

  describe('requestDisclosure', () => {
    it('sends request and returns disclosure', async () => {
      const result = await requestDisclosure(1, 'Benoetige Patientendaten fuer Rueckruf.')

      expect(result).toEqual(mockDisclosureRequest)
      expect(result.case_id).toBe(1)
      expect(result.status).toBe('pending')
    })

    it('throws on error', async () => {
      server.use(
        http.post('/api/cases/:caseId/disclosure-request', () => {
          return HttpResponse.json(
            { detail: 'Case not found' },
            { status: 404 },
          )
        }),
      )

      await expect(requestDisclosure(999, 'reason')).rejects.toThrow()
    })
  })

  // ---------- getDisclosureRequests ----------

  describe('getDisclosureRequests', () => {
    it('returns list of disclosure requests', async () => {
      const result = await getDisclosureRequests()

      expect(result).toEqual([mockDisclosureRequest])
      expect(Array.isArray(result)).toBe(true)
    })

    it('passes status parameter', async () => {
      let capturedUrl: string | undefined
      server.use(
        http.get('/api/admin/disclosure-requests', ({ request }) => {
          capturedUrl = request.url
          return HttpResponse.json([mockDisclosureApproved])
        }),
      )

      const result = await getDisclosureRequests('approved')

      expect(capturedUrl).toContain('status=approved')
      expect(result).toEqual([mockDisclosureApproved])
    })

    it('works without status filter', async () => {
      let capturedUrl: string | undefined
      server.use(
        http.get('/api/admin/disclosure-requests', ({ request }) => {
          capturedUrl = request.url
          return HttpResponse.json([mockDisclosureRequest])
        }),
      )

      const result = await getDisclosureRequests()

      expect(capturedUrl).not.toContain('status=')
      expect(result).toEqual([mockDisclosureRequest])
    })
  })

  // ---------- getDisclosureCount ----------

  describe('getDisclosureCount', () => {
    it('returns pending count', async () => {
      const result = await getDisclosureCount()

      expect(result).toBe(1)
      expect(typeof result).toBe('number')
    })
  })

  // ---------- reviewDisclosure ----------

  describe('reviewDisclosure', () => {
    it('approves a disclosure request', async () => {
      let capturedBody: Record<string, unknown> | undefined
      server.use(
        http.put('/api/admin/disclosure-requests/:id', async ({ request }) => {
          capturedBody = (await request.json()) as Record<string, unknown>
          return HttpResponse.json(mockDisclosureApproved)
        }),
      )

      const result = await reviewDisclosure(1, 'approved')

      expect(result).toEqual(mockDisclosureApproved)
      expect(result.status).toBe('approved')
      expect(capturedBody).toEqual({ status: 'approved' })
    })

    it('rejects a disclosure request', async () => {
      const rejectedDisclosure = {
        ...mockDisclosureRequest,
        status: 'rejected' as const,
        reviewed_by: 1,
        reviewed_at: '2026-02-26T09:30:00Z',
      }

      let capturedBody: Record<string, unknown> | undefined
      server.use(
        http.put('/api/admin/disclosure-requests/:id', async ({ request }) => {
          capturedBody = (await request.json()) as Record<string, unknown>
          return HttpResponse.json(rejectedDisclosure)
        }),
      )

      const result = await reviewDisclosure(1, 'rejected')

      expect(result.status).toBe('rejected')
      expect(capturedBody).toEqual({ status: 'rejected' })
    })
  })
})
