/**
 * End-to-End Integration Tests
 * Tests complete user flows and system integration
 */

import { describe, it, expect, beforeAll, afterAll } from 'vitest'
import { ApolloServer } from '@apollo/server'
import { schema } from '../../schema'
import { getDb, closeDb } from '../../db'
import { Context } from '../../types/context'

interface CreateResourceResponse {
  createResource: {
    id: string
    name: string
    status: string
  }
}

interface ResourceResponse {
  resource: {
    id: string
    name: string
    status: string
  }
}

interface AnomaliesResponse {
  detectAnomalies: Array<{
    id: string
    severity: string
    anomalyType: string
    value: number
  }>
}

interface PredictResponse {
  predictUsage: {
    id: string
    predictedValue: number
    confidence: number
    trend: string
  }
}

interface PillarsResponse {
  pillars: Array<{
    id: string
    code: string
    name: string
    controls: Array<{
      id: string
      code: string
      name: string
    }>
  }>
}

interface FindingsResponse {
  findings: Array<{
    id: string
    status: string
    severity: string
    title: string
  }>
}

describe('End-to-End Integration Tests', () => {
  let server: ApolloServer
  let testContext: Context

  beforeAll(async () => {
    server = new ApolloServer({
      schema,
    })

    const db = getDb()
    testContext = {
      request: {} as never, // Mock request for tests
      db,
      user: {
        id: 'test-user',
        email: 'test@example.com',
        name: 'Test User',
        role: 'ADMIN' as const,
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    }
  })

  afterAll(async () => {
    await server.stop()
    await closeDb()
  })

  describe('Resource Provisioning Flow', () => {
    it('should create resource and record on blockchain', async () => {
      // 1. Create resource
      const createResult = await server.executeOperation(
        {
          query: `
            mutation {
              createResource(input: {
                name: "test-vm"
                type: VM
                siteId: "site-1"
                metadata: { cpu: 4, memory: "8Gi" }
              }) {
                id
                name
                status
              }
            }
          `,
        },
        { contextValue: testContext }
      )

      expect(createResult.body.kind).toBe('single')
      if (createResult.body.kind === 'single') {
        const createData = createResult.body.singleResult.data as CreateResourceResponse | null | undefined
        const resource = createData?.createResource
        expect(resource).toBeDefined()
        if (resource) {
          expect(resource.name).toBe('test-vm')

          // 2. Query resource
          const queryResult = await server.executeOperation(
            {
              query: `
                query {
                  resource(id: "${resource.id}") {
                    id
                    name
                    status
                  }
                }
              `,
            },
            { contextValue: testContext }
          )

          expect(queryResult.body.kind).toBe('single')
          if (queryResult.body.kind === 'single') {
            const queryData = queryResult.body.singleResult.data as ResourceResponse | null | undefined
            expect(queryData?.resource.id).toBe(resource.id)
          }
        }
      }
    })
  })

  describe('Metrics and Anomaly Detection Flow', () => {
    it('should detect anomalies in metrics', async () => {
      // 1. Record metrics
      // (This would typically be done by a metrics collector)

      // 2. Detect anomalies
      const detectResult = await server.executeOperation(
        {
          query: `
            mutation {
              detectAnomalies(config: {
                resourceId: "resource-1"
                metricType: "CPU_USAGE"
                sensitivity: "MEDIUM"
              }) {
                id
                severity
                anomalyType
                value
              }
            }
          `,
        },
        { contextValue: testContext }
      )

      expect(detectResult.body.kind).toBe('single')
      if (detectResult.body.kind === 'single') {
        const data = detectResult.body.singleResult.data as AnomaliesResponse | null | undefined
        const anomalies = data?.detectAnomalies
        expect(Array.isArray(anomalies)).toBe(true)
      }
    })
  })

  describe('Predictive Analytics Flow', () => {
    it('should predict resource usage', async () => {
      const predictResult = await server.executeOperation(
        {
          query: `
            mutation {
              predictUsage(config: {
                resourceId: "resource-1"
                metricType: "CPU_USAGE"
                timeframe: "24H"
                predictionType: "USAGE"
              }) {
                id
                predictedValue
                confidence
                trend
              }
            }
          `,
        },
        { contextValue: testContext }
      )

      expect(predictResult.body.kind).toBe('single')
      if (predictResult.body.kind === 'single') {
        const data = predictResult.body.singleResult.data as PredictResponse | null | undefined
        const prediction = data?.predictUsage
        expect(prediction).toBeDefined()
        if (prediction) {
          expect(prediction.confidence).toBeGreaterThan(0)
        }
      }
    })
  })

  describe('Well-Architected Framework Flow', () => {
    it('should assess resources and generate findings', async () => {
      // 1. Get pillars
      const pillarsResult = await server.executeOperation(
        {
          query: `
            query {
              pillars {
                id
                code
                name
                controls {
                  id
                  code
                  name
                }
              }
            }
          `,
        },
        { contextValue: testContext }
      )

      expect(pillarsResult.body.kind).toBe('single')
      if (pillarsResult.body.kind === 'single') {
        const data = pillarsResult.body.singleResult.data as PillarsResponse | null | undefined
        const pillars = data?.pillars
        expect(Array.isArray(pillars)).toBe(true)
        expect(pillars?.length).toBeGreaterThan(0)
      }

      // 2. Get findings
      const findingsResult = await server.executeOperation(
        {
          query: `
            query {
              findings {
                id
                status
                severity
                title
              }
            }
          `,
        },
        { contextValue: testContext }
      )

      expect(findingsResult.body.kind).toBe('single')
      if (findingsResult.body.kind === 'single') {
        const data = findingsResult.body.singleResult.data as FindingsResponse | null | undefined
        const findings = data?.findings
        expect(Array.isArray(findings)).toBe(true)
      }
    })
  })
})

