import { describe, it, expect } from 'vitest'
import { CircuitBreakerOpenError } from '../circuit-breaker'
import { ExecutionError } from '../../../base/errors'

describe('CircuitBreakerOpenError', () => {
  describe('inheritance', () => {
    it('extends ExecutionError', () => {
      const error = new CircuitBreakerOpenError('gpt-4')
      expect(error).toBeInstanceOf(ExecutionError)
      expect(error).toBeInstanceOf(Error)
    })
  })

  describe('properties', () => {
    it('has critical severity', () => {
      const error = new CircuitBreakerOpenError('gpt-4')
      expect(error.severity).toBe('critical')
    })

    it('has system category', () => {
      const error = new CircuitBreakerOpenError('gpt-4')
      expect(error.category).toBe('system')
    })

    it('is retryable (circuit breaker handles delay)', () => {
      const error = new CircuitBreakerOpenError('gpt-4')
      expect(error.isRetryable()).toBe(true)
    })

    it('sets descriptive message with model name', () => {
      const error = new CircuitBreakerOpenError('claude-3')
      expect(error.message).toBe(
        "Circuit breaker open for model 'claude-3' - too many recent failures"
      )
    })

    it('sets name to CircuitBreakerOpenError', () => {
      const error = new CircuitBreakerOpenError('gpt-4')
      expect(error.name).toBe('CircuitBreakerOpenError')
    })

    it('has correct error name', () => {
      const error = new CircuitBreakerOpenError('gpt-4')
      expect(error.name).toBe('CircuitBreakerOpenError')
    })
  })

  describe('context', () => {
    it('includes modelName in context', () => {
      const error = new CircuitBreakerOpenError('gpt-4')
      expect(error.context).toEqual({ modelName: 'gpt-4' })
    })

    it('merges additional context with modelName', () => {
      const additionalContext = { failureCount: 5, lastFailureTime: 123456789 }
      const error = new CircuitBreakerOpenError('claude-3', additionalContext)
      expect(error.context).toEqual({
        modelName: 'claude-3',
        failureCount: 5,
        lastFailureTime: 123456789,
      })
    })
  })

  describe('stack traces', () => {
    it('captures stack trace', () => {
      const error = new CircuitBreakerOpenError('gpt-4')
      expect(error.stack).toBeDefined()
      expect(error.stack).toContain('CircuitBreakerOpenError')
    })

    it('preserves stack trace origin', () => {
      function throwCircuitBreakerError() {
        throw new CircuitBreakerOpenError('gpt-4')
      }

      try {
        throwCircuitBreakerError()
      } catch (error) {
        expect(error).toBeInstanceOf(CircuitBreakerOpenError)
        expect((error as Error).stack).toContain('throwCircuitBreakerError')
      }
    })
  })

  describe('instanceof checks', () => {
    it('maintains inheritance chain', () => {
      const error = new CircuitBreakerOpenError('gpt-4')
      expect(error instanceof CircuitBreakerOpenError).toBe(true)
      expect(error instanceof ExecutionError).toBe(true)
      expect(error instanceof Error).toBe(true)
    })
  })
})
