/**
 * Inference Server Service Tests
 */

import { describe, it, expect, beforeEach, vi } from 'vitest'
import { createInferenceEndpoint } from '../inference-server'
import type { Context } from '../../types/context'
import * as k8s from '@kubernetes/client-node'

// Mock Kubernetes client
vi.mock('@kubernetes/client-node', () => ({
  KubeConfig: vi.fn().mockImplementation(() => ({
    loadFromDefault: vi.fn(),
    makeApiClient: vi.fn(),
  })),
  AppsV1Api: vi.fn(),
  CoreV1Api: vi.fn(),
}))

describe('Inference Server Service', () => {
  let mockContext: Context
  let mockAppsApi: any
  let mockCoreApi: any

  beforeEach(() => {
    mockAppsApi = {
      createNamespacedDeployment: vi.fn(),
    }

    mockCoreApi = {
      readNamespace: vi.fn(),
      createNamespace: vi.fn(),
      createNamespacedService: vi.fn(),
    }

    const mockKc = {
      loadFromDefault: vi.fn(),
      makeApiClient: vi.fn((api: any) => {
        if (api === k8s.AppsV1Api) return mockAppsApi
        if (api === k8s.CoreV1Api) return mockCoreApi
        return mockCoreApi
      }),
    }

    vi.mocked(k8s.KubeConfig).mockImplementation(() => mockKc as any)

    mockContext = {
      db: {} as any,
      user: {
        id: 'user-1',
        email: 'test@example.com',
        name: 'Test User',
        role: 'ADMIN',
      },
    } as Context
  })

  describe('createInferenceEndpoint', () => {
    it('should create a Kubernetes deployment for inference', async () => {
      mockCoreApi.readNamespace.mockRejectedValue({ statusCode: 404 })
      mockCoreApi.createNamespace.mockResolvedValue({})
      mockAppsApi.createNamespacedDeployment.mockResolvedValue({
        body: {
          metadata: {
            name: 'inference-test-model',
            namespace: 'inference',
          },
          spec: {
            replicas: 1,
            template: {
              spec: {
                containers: [
                  {
                    name: 'inference',
                    image: 'model-registry/test-model:latest',
                  },
                ],
              },
            },
          },
        },
      })
      mockCoreApi.createNamespacedService.mockResolvedValue({})

      const result = await createInferenceEndpoint(mockContext, {
        name: 'test-model',
        modelId: 'test-model',
        image: 'model-registry/test-model:latest',
        namespace: 'inference',
        replicas: 1,
        port: 8080,
      })

      expect(result).toBeDefined()
      expect(result.name).toBe('test-model')
      expect(result.modelId).toBe('test-model')
      expect(result.status).toBe('PROVISIONING')
      expect(mockAppsApi.createNamespacedDeployment).toHaveBeenCalled()
      expect(mockCoreApi.createNamespacedService).toHaveBeenCalled()
    })

    it('should support GPU allocation', async () => {
      mockCoreApi.readNamespace.mockResolvedValue({})
      mockAppsApi.createNamespacedDeployment.mockResolvedValue({
        body: {
          metadata: { name: 'inference-test', namespace: 'inference' },
        },
      })
      mockCoreApi.createNamespacedService.mockResolvedValue({})

      await createInferenceEndpoint(mockContext, {
        name: 'test-model',
        modelId: 'test-model',
        resources: {
          gpu: 1,
          cpu: '2000m',
          memory: '4Gi',
        },
      })

      const deploymentCall = mockAppsApi.createNamespacedDeployment.mock.calls[0]
      const deployment = deploymentCall[1]
      expect(deployment.spec.template.spec.containers[0].resources.limits['nvidia.com/gpu']).toBe('1')
    })
  })
})

