import { describe, it, expect, vi, beforeEach } from 'vitest'
import { supabaseAreaRepo } from '@/persistence/supabase/area-repo'

const { mockSingle, mockData } = vi.hoisted(() => ({
  mockSingle: vi.fn(),
  mockData: vi.fn(),
}))

vi.mock('@/lib/supabase', () => {
  const buildChain = () => {
    const chain: Record<string, unknown> = {}
    chain.select = vi.fn().mockReturnValue(chain)
    chain.insert = vi.fn().mockReturnValue(chain)
    chain.update = vi.fn().mockReturnValue(chain)
    chain.delete = vi.fn().mockReturnValue(chain)
    chain.eq = vi.fn().mockReturnValue(chain)
    chain.order = vi.fn().mockImplementation(() => mockData())
    chain.single = mockSingle
    return chain
  }

  return {
    supabase: {
      from: vi.fn().mockImplementation(() => buildChain()),
    },
  }
})

const AREA_ROW = {
  id: 'area-uuid-1',
  org_id: 'org-uuid-1',
  name: 'Finanzas',
  description: 'Área de finanzas',
  created_at: '2026-07-07T00:00:00.000Z',
  updated_at: '2026-07-07T00:00:00.000Z',
}

describe('supabaseAreaRepo', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  describe('getByOrg', () => {
    it('devuelve lista de áreas mapeadas correctamente', async () => {
      mockData.mockResolvedValue({ data: [AREA_ROW], error: null })

      const result = await supabaseAreaRepo.getByOrg('org-uuid-1')

      expect(result).toHaveLength(1)
      expect(result[0]).toMatchObject({
        id: 'area-uuid-1',
        orgId: 'org-uuid-1',
        name: 'Finanzas',
        description: 'Área de finanzas',
        createdAt: new Date('2026-07-07T00:00:00.000Z').getTime(),
      })
    })

    it('devuelve array vacío si la org no tiene áreas', async () => {
      mockData.mockResolvedValue({ data: [], error: null })

      const result = await supabaseAreaRepo.getByOrg('org-sin-areas')

      expect(result).toEqual([])
    })
  })

  describe('create', () => {
    it('inserta el área y retorna el registro mapeado', async () => {
      mockSingle.mockResolvedValue({ data: AREA_ROW, error: null })

      const result = await supabaseAreaRepo.create({
        orgId: 'org-uuid-1',
        name: 'Finanzas',
        description: 'Área de finanzas',
      })

      expect(result).toMatchObject({
        id: 'area-uuid-1',
        orgId: 'org-uuid-1',
        name: 'Finanzas',
        description: 'Área de finanzas',
      })
    })

    it('propaga el error de Supabase si el insert falla', async () => {
      mockSingle.mockResolvedValue({ data: null, error: new Error('RLS violation') })

      await expect(
        supabaseAreaRepo.create({ orgId: 'org-1', name: 'Test' })
      ).rejects.toThrow('RLS violation')
    })
  })
})
