/**
 * ConfigManager Unit Tests
 *
 * Tests for ConfigManager default configuration values, schema validation,
 * and singleton behavior.
 * Logger is mocked to isolate ConfigManager testing.
 */

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'

// Mock logger to prevent initialization issues
vi.mock('../../src/main/services/logger', () => ({
  createLogger: vi.fn(() => ({
    info: vi.fn(),
    error: vi.fn(),
    warn: vi.fn(),
    debug: vi.fn()
  })),
  applyLoggingConfig: vi.fn(),
  trackDuration: vi.fn()
}))

// Mock audit-logger
vi.mock('../../src/main/services/logger/audit-logger', () => ({
  applyAuditConfig: vi.fn()
}))

describe('ConfigManager', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  afterEach(() => {
    vi.resetModules()
  })

  it('should return default config with correct logging values', async () => {
    const { ConfigManager } = await import('../../src/main/services/config/config-manager')

    const manager = ConfigManager.getInstance()
    const defaultConfig = manager.getDefaultConfig()

    expect(defaultConfig.logging.level).toBe('info')
    expect(defaultConfig.logging.auditRetention).toBe(30)
    expect(defaultConfig.logging.appRetention).toBe(14)
  })

  it('should return default config with correct database defaults', async () => {
    const { ConfigManager } = await import('../../src/main/services/config/config-manager')

    const manager = ConfigManager.getInstance()
    const defaultConfig = manager.getDefaultConfig()

    expect(defaultConfig.database.activeType).toBe('mysql')
    expect(defaultConfig.database.mysql.host).toBe('localhost')
    expect(defaultConfig.database.mysql.port).toBe(3306)
    expect(defaultConfig.database.mysql.database).toBe('erp_db')
  })

  it('should return default config with correct extraction defaults', async () => {
    const { ConfigManager } = await import('../../src/main/services/config/config-manager')

    const manager = ConfigManager.getInstance()
    const defaultConfig = manager.getDefaultConfig()

    expect(defaultConfig.extraction.batchSize).toBe(100)
    expect(defaultConfig.extraction.headless).toBe(true)
    expect(defaultConfig.extraction.autoConvert).toBe(true)
  })

  it('should throw when getConfig() is called before initialize()', async () => {
    const { ConfigManager } = await import('../../src/main/services/config/config-manager')

    // Reset singleton to get a fresh uninitialized instance
    const FreshConfigManager = ConfigManager as any
    FreshConfigManager.instance = null

    const manager = ConfigManager.getInstance()

    expect(() => manager.getConfig()).toThrow('Configuration not initialized')
  })

  it('should return the same singleton instance', async () => {
    const { ConfigManager } = await import('../../src/main/services/config/config-manager')

    const a = ConfigManager.getInstance()
    const b = ConfigManager.getInstance()

    expect(a).toBe(b)
  })
})

describe('Config Schema Validation', () => {
  it('should validate complete logging configuration', async () => {
    const { loggingConfigSchema } = await import('../../src/main/types/config.schema')

    const validConfig = {
      level: 'debug' as const,
      auditRetention: 60,
      appRetention: 21
    }

    const result = loggingConfigSchema.safeParse(validConfig)
    expect(result.success).toBe(true)

    if (result.success) {
      expect(result.data.level).toBe('debug')
      expect(result.data.auditRetention).toBe(60)
      expect(result.data.appRetention).toBe(21)
    }
  })

  it('should validate logging level enum values', async () => {
    const { loggingConfigSchema } = await import('../../src/main/types/config.schema')

    const validLevels = ['error', 'warn', 'info', 'debug', 'verbose']

    for (const level of validLevels) {
      const result = loggingConfigSchema.safeParse({ level })
      expect(result.success).toBe(true)
    }
  })

  it('should reject invalid logging level', async () => {
    const { loggingConfigSchema } = await import('../../src/main/types/config.schema')

    const result = loggingConfigSchema.safeParse({ level: 'invalid_level' })
    expect(result.success).toBe(false)
  })

  it('should validate audit retention range (1-365)', async () => {
    const { loggingConfigSchema } = await import('../../src/main/types/config.schema')

    expect(loggingConfigSchema.safeParse({ auditRetention: 1 }).success).toBe(true)
    expect(loggingConfigSchema.safeParse({ auditRetention: 365 }).success).toBe(true)
    expect(loggingConfigSchema.safeParse({ auditRetention: 0 }).success).toBe(false)
    expect(loggingConfigSchema.safeParse({ auditRetention: 366 }).success).toBe(false)
  })

  it('should validate app retention range (1-365)', async () => {
    const { loggingConfigSchema } = await import('../../src/main/types/config.schema')

    expect(loggingConfigSchema.safeParse({ appRetention: 1 }).success).toBe(true)
    expect(loggingConfigSchema.safeParse({ appRetention: 365 }).success).toBe(true)
    expect(loggingConfigSchema.safeParse({ appRetention: 0 }).success).toBe(false)
    expect(loggingConfigSchema.safeParse({ appRetention: 366 }).success).toBe(false)
  })

  it('should use default values when logging config is partial', async () => {
    const { loggingConfigSchema } = await import('../../src/main/types/config.schema')

    const result = loggingConfigSchema.safeParse({ level: 'warn' })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.auditRetention).toBe(30)
      expect(result.data.appRetention).toBe(14)
    }
  })
})
