/**
 * Tests for Attio listRecords fetch implementation
 */

import { describe as _describe, it, expect, vi, beforeEach } from 'vitest'

// Attio integration not in use; suite skipped per project decision (2026-04-29).
const describe = _describe.skip
import { listRecords } from './index.js'
import { ToolingError } from '../../../../../../types.js'

// Mock fetch globally
const mockFetch = vi.fn()
global.fetch = mockFetch as typeof fetch

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

  it('should list records successfully with default pagination', async () => {
    const mockResponse = {
      data: [
        {
          id: {
            workspace_id: 'workspace-123',
            object_id: 'object-456',
            record_id: 'record-1'
          },
          created_at: '2024-01-01T12:00:00Z',
          web_url: 'https://app.attio.com/workspace/record-1',
          values: {
            name: [{ first_name: 'John', last_name: 'Doe' }]
          }
        },
        {
          id: {
            workspace_id: 'workspace-123',
            object_id: 'object-456',
            record_id: 'record-2'
          },
          created_at: '2024-01-02T12:00:00Z',
          web_url: 'https://app.attio.com/workspace/record-2',
          values: {
            name: [{ first_name: 'Jane', last_name: 'Smith' }]
          }
        }
      ]
    }

    mockFetch.mockResolvedValue({
      ok: true,
      json: async () => mockResponse
    })

    const result = await listRecords({ apiKey: 'test-key' }, { object: 'people' })

    expect(result.records).toHaveLength(2)
    expect(result.records[0].id).toBe('record-1')
    expect(result.records[1].id).toBe('record-2')
    expect(result.hasMore).toBe(false) // Only 2 records, default limit is 500

    expect(mockFetch).toHaveBeenCalledWith(
      'https://api.attio.com/v2/objects/people/records/query',
      expect.objectContaining({
        method: 'POST',
        headers: {
          Authorization: 'Bearer test-key',
          'Content-Type': 'application/json',
          Accept: 'application/json'
        },
        body: JSON.stringify({
          limit: 500,
          offset: 0
        })
      })
    )
  })

  it('should support custom limit and offset', async () => {
    const mockResponse = {
      data: Array.from({ length: 50 }, (_, i) => ({
        id: {
          workspace_id: 'workspace-123',
          object_id: 'object-456',
          record_id: `record-${i + 50}`
        },
        created_at: '2024-01-01T12:00:00Z',
        web_url: `https://app.attio.com/workspace/record-${i + 50}`,
        values: {}
      }))
    }

    mockFetch.mockResolvedValue({
      ok: true,
      json: async () => mockResponse
    })

    const result = await listRecords({ apiKey: 'test-key' }, { object: 'people', limit: 50, offset: 50 })

    expect(result.records).toHaveLength(50)
    expect(result.hasMore).toBe(true) // Returned count equals limit

    const fetchCall = mockFetch.mock.calls[0][1] as { body: string }
    const calledBody = JSON.parse(fetchCall.body)
    expect(calledBody.limit).toBe(50)
    expect(calledBody.offset).toBe(50)
  })

  it('should support filter parameters', async () => {
    const mockResponse = { data: [] }

    mockFetch.mockResolvedValue({
      ok: true,
      json: async () => mockResponse
    })

    await listRecords(
      { apiKey: 'test-key' },
      {
        object: 'people',
        filter: {
          name: {
            first_name: {
              $eq: 'John'
            }
          }
        }
      }
    )

    const fetchCall = mockFetch.mock.calls[0][1] as { body: string }
    const calledBody = JSON.parse(fetchCall.body)
    expect(calledBody.filter).toEqual({
      name: {
        first_name: {
          $eq: 'John'
        }
      }
    })
  })

  it('should support sorts parameters', async () => {
    const mockResponse = { data: [] }

    mockFetch.mockResolvedValue({
      ok: true,
      json: async () => mockResponse
    })

    await listRecords(
      { apiKey: 'test-key' },
      {
        object: 'people',
        sorts: [
          {
            attribute: 'name',
            field: 'last_name',
            direction: 'asc'
          }
        ]
      }
    )

    const fetchCall = mockFetch.mock.calls[0][1] as { body: string }
    const calledBody = JSON.parse(fetchCall.body)
    expect(calledBody.sorts).toEqual([
      {
        attribute: 'name',
        field: 'last_name',
        direction: 'asc'
      }
    ])
  })

  it('should support complex filters with logical operators', async () => {
    const mockResponse = { data: [] }

    mockFetch.mockResolvedValue({
      ok: true,
      json: async () => mockResponse
    })

    await listRecords(
      { apiKey: 'test-key' },
      {
        object: 'deals',
        filter: {
          $and: [
            {
              value: {
                value: {
                  $gte: 10000
                }
              }
            },
            {
              status: {
                $eq: 'open'
              }
            }
          ]
        }
      }
    )

    const fetchCall = mockFetch.mock.calls[0][1] as { body: string }
    const calledBody = JSON.parse(fetchCall.body)
    expect(calledBody.filter.$and).toHaveLength(2)
  })

  it('should throw credentials_invalid when API key is missing', async () => {
    await expect(listRecords({ apiKey: '' }, { object: 'people' })).rejects.toThrow('Missing Attio API key')
  })

  it('should throw validation_error when object is missing', async () => {
    await expect(listRecords({ apiKey: 'test-key' }, { object: '' })).rejects.toThrow(
      'Missing required parameter: object'
    )
  })

  it('should handle 401 authentication errors', async () => {
    mockFetch.mockResolvedValue({
      ok: false,
      status: 401,
      statusText: 'Unauthorized',
      text: async () =>
        JSON.stringify({
          status_code: 401,
          type: 'authentication_error',
          code: 'unauthorized',
          message: 'Invalid API key'
        })
    })

    try {
      await listRecords({ apiKey: 'invalid-key' }, { object: 'people' })
    } catch (error) {
      expect((error as ToolingError).errorType).toBe('credentials_invalid')
    }
  })

  it('should work with different object types', async () => {
    const mockResponse = {
      data: [
        {
          id: {
            workspace_id: 'workspace-123',
            object_id: 'object-456',
            record_id: 'company-1'
          },
          created_at: '2024-01-01T12:00:00Z',
          web_url: 'https://app.attio.com/workspace/company-1',
          values: {
            name: 'Acme Corp'
          }
        }
      ]
    }

    mockFetch.mockResolvedValue({
      ok: true,
      json: async () => mockResponse
    })

    const result = await listRecords({ apiKey: 'test-key' }, { object: 'companies' })

    expect(result.records).toHaveLength(1)
    expect(result.records[0].values.name).toBe('Acme Corp')

    expect(mockFetch).toHaveBeenCalledWith(
      'https://api.attio.com/v2/objects/companies/records/query',
      expect.anything()
    )
  })

  it('should determine hasMore correctly based on limit', async () => {
    // Case 1: Returned count < limit -> hasMore = false
    const mockResponse1 = {
      data: Array.from({ length: 25 }, (_, i) => ({
        id: { workspace_id: 'w', object_id: 'o', record_id: `r-${i}` },
        created_at: '2024-01-01T12:00:00Z',
        web_url: `https://app.attio.com/w/r-${i}`,
        values: {}
      }))
    }

    mockFetch.mockResolvedValueOnce({
      ok: true,
      json: async () => mockResponse1
    })

    const result1 = await listRecords({ apiKey: 'test-key' }, { object: 'people', limit: 50 })

    expect(result1.hasMore).toBe(false)

    // Case 2: Returned count = limit -> hasMore = true
    const mockResponse2 = {
      data: Array.from({ length: 50 }, (_, i) => ({
        id: { workspace_id: 'w', object_id: 'o', record_id: `r-${i}` },
        created_at: '2024-01-01T12:00:00Z',
        web_url: `https://app.attio.com/w/r-${i}`,
        values: {}
      }))
    }

    mockFetch.mockResolvedValueOnce({
      ok: true,
      json: async () => mockResponse2
    })

    const result2 = await listRecords({ apiKey: 'test-key' }, { object: 'people', limit: 50 })

    expect(result2.hasMore).toBe(true)
  })
})
