import { describe, expect, it } from 'vitest'

import { transformMcpServer } from '../McpServerMappings'

const NULL_FIELDS = {
  type: null,
  description: null,
  baseUrl: null,
  command: null,
  registryUrl: null,
  args: null,
  env: null,
  headers: null,
  provider: null,
  providerUrl: null,
  logoUrl: null,
  tags: null,
  longRunning: null,
  timeout: null,
  dxtVersion: null,
  dxtPath: null,
  reference: null,
  searchKey: null,
  configSample: null,
  disabledTools: null,
  disabledAutoApproveTools: null,
  shouldConfig: null,
  installSource: null,
  isTrusted: null,
  trustedAt: null,
  installedAt: null
}

describe('McpServerMappings', () => {
  describe('transformMcpServer', () => {
    it('should transform a full McpServer record (id excluded, auto-generated by DB)', () => {
      const fields = {
        name: '@cherry/fetch',
        type: 'inMemory',
        description: 'Fetch tool',
        baseUrl: 'http://localhost:3000',
        command: 'npx',
        registryUrl: 'https://registry.example.com',
        args: ['-y', 'some-package'],
        env: { API_KEY: 'key123' },
        headers: { Authorization: 'Bearer token' },
        provider: 'CherryAI',
        providerUrl: 'https://cherry.ai',
        logoUrl: 'https://cherry.ai/logo.png',
        tags: ['search', 'web'],
        longRunning: true,
        timeout: 120,
        dxtVersion: '1.0.0',
        dxtPath: '/path/to/dxt',
        reference: 'https://docs.example.com',
        searchKey: 'fetch-tool',
        configSample: { command: 'npx', args: ['-y', 'some-package'], env: { API_KEY: 'key123' } },
        disabledTools: ['tool1'],
        disabledAutoApproveTools: ['tool2'],
        shouldConfig: true,
        isActive: true,
        installSource: 'builtin',
        isTrusted: true,
        trustedAt: 1700000000000,
        installedAt: 1699000000000
      }

      const result = transformMcpServer({ id: 'srv-1', ...fields }, 0)
      expect(result.oldId).toBe('srv-1')
      expect(result.row).toStrictEqual(expect.objectContaining({ ...fields, sortOrder: 0 }))
      // New ID is a UUID, different from the old one
      expect(result.row.id).toBeDefined()
      expect(result.row.id).not.toBe('srv-1')
    })

    it('should handle minimal McpServer (only required fields)', () => {
      const result = transformMcpServer({ id: 'srv-2', name: 'my-server', isActive: false }, 3)
      expect(result.oldId).toBe('srv-2')
      expect(result.row).toStrictEqual(
        expect.objectContaining({
          ...NULL_FIELDS,
          name: 'my-server',
          sortOrder: 3,
          isActive: false
        })
      )
    })

    it('should handle null and undefined optional fields', () => {
      const source = {
        id: 'srv-3',
        name: 'test',
        isActive: true,
        type: undefined,
        description: null,
        args: undefined,
        env: null
      }
      const result = transformMcpServer(source as any, 0)
      expect(result.row).toStrictEqual(
        expect.objectContaining({
          ...NULL_FIELDS,
          name: 'test',
          sortOrder: 0,
          isActive: true
        })
      )
    })

    it('should default isActive to false when missing', () => {
      const result = transformMcpServer({ id: 'srv-4', name: 'no-active-field' } as any, 0)
      expect(result.row).toStrictEqual(
        expect.objectContaining({
          ...NULL_FIELDS,
          name: 'no-active-field',
          sortOrder: 0,
          isActive: false
        })
      )
    })

    it('should preserve empty arrays', () => {
      const result = transformMcpServer(
        {
          id: 'srv-5',
          name: 'empty-arrays',
          isActive: false,
          args: [],
          tags: [],
          disabledTools: []
        },
        0
      )
      expect(result.row).toStrictEqual(
        expect.objectContaining({
          ...NULL_FIELDS,
          name: 'empty-arrays',
          sortOrder: 0,
          isActive: false,
          args: [],
          tags: [],
          disabledTools: []
        })
      )
    })

    it('should fall back from url to baseUrl for SSE servers', () => {
      const result = transformMcpServer(
        {
          id: 'sse-1',
          name: 'sse-server',
          isActive: true,
          url: 'http://localhost:8080/sse'
        },
        0
      )
      expect(result.row.baseUrl).toBe('http://localhost:8080/sse')
    })

    it('should prefer baseUrl over url when both present', () => {
      const result = transformMcpServer(
        {
          id: 'sse-2',
          name: 'sse-server',
          isActive: true,
          baseUrl: 'http://primary:8080',
          url: 'http://fallback:8080'
        },
        0
      )
      expect(result.row.baseUrl).toBe('http://primary:8080')
    })

    it('should preserve empty objects', () => {
      const result = transformMcpServer(
        { id: 'srv-6', name: 'empty-objects', isActive: false, env: {}, headers: {} },
        0
      )
      expect(result.row).toStrictEqual(
        expect.objectContaining({
          ...NULL_FIELDS,
          name: 'empty-objects',
          sortOrder: 0,
          isActive: false,
          env: {},
          headers: {}
        })
      )
    })

    it('should use the provided index as sortOrder', () => {
      const result = transformMcpServer({ id: 'srv-7', name: 'ordered', isActive: false }, 5)
      expect(result.row.sortOrder).toBe(5)
    })
  })
})
