/**
 * Predictive Analytics Service Tests
 */

import { describe, it, expect, beforeEach, vi } from 'vitest'
import { predictUsage, predictCost, predictCapacity } from '../predictive-analytics'
import type { Context } from '../../types/context'

describe('Predictive Analytics Service', () => {
  let mockContext: Context
  let mockDb: any

  beforeEach(() => {
    mockDb = {
      query: vi.fn(),
    }

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

  describe('predictUsage', () => {
    it('should predict future usage based on historical data', async () => {
      // Mock increasing trend in metrics
      const metrics = Array.from({ length: 100 }, (_, i) => ({
        timestamp: new Date(Date.now() - (100 - i) * 60000),
        value: (50 + i * 0.5).toString(), // Increasing trend
      }))

      mockDb.query
        .mockResolvedValueOnce({ rows: metrics })
        .mockResolvedValue({ rows: [] }) // For storing prediction

      const prediction = await predictUsage(mockContext, {
        resourceId: 'resource-1',
        metricType: 'CPU_USAGE',
        timeframe: '24H',
        predictionType: 'USAGE',
      })

      expect(prediction).toBeDefined()
      expect(prediction.predictedValue).toBeGreaterThan(prediction.currentValue)
      expect(prediction.trend).toBe('INCREASING')
      expect(prediction.confidence).toBeGreaterThan(0)
    })

    it('should throw error with insufficient data', async () => {
      mockDb.query.mockResolvedValue({ rows: Array.from({ length: 5 }) })

      await expect(
        predictUsage(mockContext, {
          resourceId: 'resource-1',
          metricType: 'CPU_USAGE',
          timeframe: '24H',
          predictionType: 'USAGE',
        })
      ).rejects.toThrow('Insufficient historical data')
    })
  })

  describe('predictCost', () => {
    it('should predict future costs', async () => {
      const metrics = Array.from({ length: 100 }, (_, i) => ({
        timestamp: new Date(Date.now() - (100 - i) * 60000),
        value: (100 + i * 0.1).toString(),
      }))

      mockDb.query
        .mockResolvedValueOnce({ rows: metrics })
        .mockResolvedValue({ rows: [] })

      const prediction = await predictCost(mockContext, 'resource-1', '7D')

      expect(prediction).toBeDefined()
      expect(prediction.predictionType).toBe('COST')
      expect(prediction.metricType).toBe('COST')
    })
  })

  describe('predictCapacity', () => {
    it('should predict capacity needs with recommendations', async () => {
      // Mock high usage trend
      const metrics = Array.from({ length: 100 }, (_, i) => ({
        timestamp: new Date(Date.now() - (100 - i) * 60000),
        value: (70 + i * 0.3).toString(), // Increasing towards capacity limit
      }))

      mockDb.query
        .mockResolvedValueOnce({ rows: metrics })
        .mockResolvedValue({ rows: [] })

      const prediction = await predictCapacity(mockContext, 'resource-1', 'CPU_USAGE', '24H')

      expect(prediction).toBeDefined()
      expect(prediction.predictionType).toBe('CAPACITY')
      if (prediction.predictedValue > 80) {
        expect(prediction.recommendation).toContain('scaling')
      }
    })
  })
})

