/**
 * Policy Engine Service Tests
 */

import { describe, it, expect, beforeEach, vi } from 'vitest'
import * as policyService from '../policy-engine'
import type { Context } from '../../types/context'

describe('Policy Engine 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('evaluatePolicy', () => {
    it('should evaluate a policy against a resource', async () => {
      const mockPolicy = {
        id: 'policy-1',
        name: 'Tagging Policy',
        rule: JSON.stringify({
          type: 'tagging',
          requiredTags: ['environment', 'team'],
        }),
      }

      const mockResource = {
        id: 'resource-1',
        tags: JSON.stringify(['environment:prod', 'team:backend']),
      }

      mockDb.query
        .mockResolvedValueOnce({ rows: [mockPolicy] })
        .mockResolvedValueOnce({ rows: [mockResource] })
        .mockResolvedValueOnce({
          rows: [
            {
              id: 'eval-1',
              policy_id: 'policy-1',
              resource_id: 'resource-1',
              status: 'COMPLIANT',
              findings: JSON.stringify([]),
              evaluated_at: new Date(),
            },
          ],
        })

      const evaluation = await policyService.evaluatePolicy(
        mockContext,
        'policy-1',
        'resource-1'
      )

      expect(evaluation).toBeDefined()
      expect(evaluation.status).toBe('COMPLIANT')
    })

    it('should detect policy violations', async () => {
      const mockPolicy = {
        id: 'policy-1',
        name: 'Tagging Policy',
        rule: JSON.stringify({
          type: 'tagging',
          requiredTags: ['environment', 'team'],
        }),
      }

      const mockResource = {
        id: 'resource-1',
        tags: JSON.stringify(['environment:prod']), // Missing 'team' tag
      }

      mockDb.query
        .mockResolvedValueOnce({ rows: [mockPolicy] })
        .mockResolvedValueOnce({ rows: [mockResource] })
        .mockResolvedValueOnce({
          rows: [
            {
              id: 'eval-1',
              policy_id: 'policy-1',
              resource_id: 'resource-1',
              status: 'NON_COMPLIANT',
              findings: JSON.stringify([
                { tag: 'team', reason: 'Missing required tag' },
              ]),
              evaluated_at: new Date(),
            },
          ],
        })
        .mockResolvedValueOnce({
          rows: [
            {
              id: 'violation-1',
              policy_id: 'policy-1',
              resource_id: 'resource-1',
              severity: 'MEDIUM',
              message: 'Missing required tag: team',
              status: 'OPEN',
              created_at: new Date(),
            },
          ],
        })

      const evaluation = await policyService.evaluatePolicy(
        mockContext,
        'policy-1',
        'resource-1'
      )

      expect(evaluation.status).toBe('NON_COMPLIANT')
      expect(evaluation.findings.length).toBeGreaterThan(0)
    })
  })

  describe('evaluateAllPolicies', () => {
    it('should evaluate all enabled policies', async () => {
      const mockPolicies = [
        { id: 'policy-1', enabled: true },
        { id: 'policy-2', enabled: true },
      ]

      mockDb.query
        .mockResolvedValueOnce({ rows: mockPolicies })
        .mockResolvedValue({ rows: [] }) // Evaluation results

      const result = await policyService.evaluateAllPolicies(mockContext)

      expect(result.evaluated).toBeGreaterThanOrEqual(0)
    })
  })
})

