/**
 * GenUI Registry 單元測試
 * =======================
 * Phase 19.6: Zod Schema 驗證 + Registry API 測試
 *
 * 測試內容:
 * 1. Zod Schema 驗證 — 每個組件的合法/非法 Props
 * 2. Registry API — getComponent, isRegistered, getRegisteredComponents
 * 3. getTerminalComponents — 只返回 allowInTerminal=true 的組件
 * 4. validateProps — 錯誤碼分類 (UNKNOWN_COMPONENT / ZOD_VALIDATION_FAILED)
 *
 * 注意：registry.ts 使用 React.lazy，在 Node 環境需以測試替身隔離 lazy 載入
 *
 * @see ADR-032 GenUI Dynamic Rendering
 * Phase 19.6 ogt 2026-03-31 (台北時間)
 */

import { vi, describe, it, expect, beforeAll } from 'vitest'

// ===== React lazy 測試替身（Node 環境無法執行 lazy import） =====
vi.mock('react', () => ({
  lazy: vi.fn((factory: () => Promise<unknown>) => factory),
}))

// ===== Import 測試目標 =====
import {
  GENUI_REGISTRY,
  ApprovalCardSchema,
  MetricsSummaryCardSchema,
  SentryErrorCardSchema,
  IncidentTimelineCardSchema,
  K8sPodStatusCardSchema,
  TraceWaterfallCardSchema,
  NuclearKeyButtonSchema,
  getComponent,
  isRegistered,
  getRegisteredComponents,
  getTerminalComponents,
  validateProps,
} from '../registry'

// =============================================================================
// Registry 基礎 API
// =============================================================================

describe('Registry 基礎 API', () => {
  it('應有 7 個已註冊組件', () => {
    const names = getRegisteredComponents()
    expect(names).toHaveLength(7)
  })

  it('getRegisteredComponents 包含所有預期組件', () => {
    const names = getRegisteredComponents()
    const expected = [
      'ApprovalCard',
      'MetricsSummaryCard',
      'SentryErrorCard',
      'IncidentTimelineCard',
      'K8sPodStatusCard',
      'TraceWaterfallCard',
      'NuclearKeyButton',
    ]
    expected.forEach(name => expect(names).toContain(name))
  })

  it('getComponent 已知組件返回定義', () => {
    const def = getComponent('ApprovalCard')
    expect(def).toBeDefined()
    expect(def!.name).toBe('ApprovalCard')
    expect(def!.allowInTerminal).toBe(true)
  })

  it('getComponent 未知組件返回 undefined', () => {
    expect(getComponent('NonExistentComponent')).toBeUndefined()
  })

  it('isRegistered 已知組件返回 true', () => {
    expect(isRegistered('ApprovalCard')).toBe(true)
    expect(isRegistered('NuclearKeyButton')).toBe(true)
  })

  it('isRegistered 未知組件返回 false', () => {
    expect(isRegistered('FakeCard')).toBe(false)
    expect(isRegistered('')).toBe(false)
  })

  it('所有組件都設定 allowInTerminal=true', () => {
    const components = getTerminalComponents()
    expect(components).toHaveLength(7)
    components.forEach(c => expect(c.allowInTerminal).toBe(true))
  })
})

// =============================================================================
// validateProps — 錯誤碼分類
// =============================================================================

describe('validateProps 錯誤碼分類', () => {
  it('未知組件返回 UNKNOWN_COMPONENT 錯誤碼', () => {
    const result = validateProps('UnknownCard', { foo: 'bar' })
    expect(result.valid).toBe(false)
    expect(result.errorCode).toBe('UNKNOWN_COMPONENT')
    expect(result.errors).toHaveLength(1)
  })

  it('合法 Props 返回 valid=true，無錯誤', () => {
    const result = validateProps('ApprovalCard', {
      approvalId: 'APR-001',
      riskLevel: 'critical',
      kubectl: 'kubectl delete pod foo',
    })
    expect(result.valid).toBe(true)
    expect(result.errors).toHaveLength(0)
    expect(result.errorCode).toBeUndefined()
  })

  it('非法 Props 返回 ZOD_VALIDATION_FAILED 錯誤碼', () => {
    const result = validateProps('ApprovalCard', {
      approvalId: '',           // min_length=1 違規
      riskLevel: 'extreme',     // 不在 enum 中
    })
    expect(result.valid).toBe(false)
    expect(result.errorCode).toBe('ZOD_VALIDATION_FAILED')
    expect(result.errors.length).toBeGreaterThan(0)
  })

  it('NuclearKeyButton 缺少必填 label 應失敗', () => {
    const result = validateProps('NuclearKeyButton', {
      riskLevel: 'high',
      // label 缺失
    })
    expect(result.valid).toBe(false)
    expect(result.errorCode).toBe('ZOD_VALIDATION_FAILED')
  })
})

// =============================================================================
// ApprovalCardSchema
// =============================================================================

describe('ApprovalCardSchema', () => {
  it('合法 Props 通過驗證', () => {
    const result = ApprovalCardSchema.safeParse({
      approvalId: 'APR-2026-0001',
      riskLevel: 'critical',
      kubectl: 'kubectl drain node-01',
    })
    expect(result.success).toBe(true)
  })

  it('kubectl 為選填欄位', () => {
    const result = ApprovalCardSchema.safeParse({
      approvalId: 'APR-001',
      riskLevel: 'low',
    })
    expect(result.success).toBe(true)
  })

  it('空 approvalId 不通過 (min_length=1)', () => {
    const result = ApprovalCardSchema.safeParse({
      approvalId: '',
      riskLevel: 'medium',
    })
    expect(result.success).toBe(false)
  })

  it('非法 riskLevel 不通過', () => {
    const result = ApprovalCardSchema.safeParse({
      approvalId: 'APR-001',
      riskLevel: 'extreme',   // 不在 enum 中
    })
    expect(result.success).toBe(false)
  })

  it('所有合法 riskLevel 通過', () => {
    const levels = ['low', 'medium', 'high', 'critical'] as const
    levels.forEach(level => {
      const result = ApprovalCardSchema.safeParse({ approvalId: 'x', riskLevel: level })
      expect(result.success).toBe(true)
    })
  })
})

// =============================================================================
// MetricsSummaryCardSchema
// =============================================================================

describe('MetricsSummaryCardSchema', () => {
  it('合法 Props 通過驗證', () => {
    const result = MetricsSummaryCardSchema.safeParse({
      rps: 150.5,
      errorRate: '0.05%',
      p99Latency: '450ms',
      status: 'healthy',
    })
    expect(result.success).toBe(true)
  })

  it('errorRate 格式必須為百分比 (e.g. "0.05%")', () => {
    const invalidFormats = ['0.05', '5 percent', 'high']
    invalidFormats.forEach(fmt => {
      const result = MetricsSummaryCardSchema.safeParse({
        rps: 100, errorRate: fmt, p99Latency: '100ms', status: 'healthy',
      })
      expect(result.success).toBe(false)
    })
  })

  it('p99Latency 格式必須為時間 (e.g. "450ms" 或 "1.5s")', () => {
    const invalidFormats = ['450', '1.5 seconds', 'fast']
    invalidFormats.forEach(fmt => {
      const result = MetricsSummaryCardSchema.safeParse({
        rps: 100, errorRate: '1%', p99Latency: fmt, status: 'healthy',
      })
      expect(result.success).toBe(false)
    })
  })

  it('合法 p99Latency 格式: ms 與 s', () => {
    const validFormats = ['100ms', '1.5s', '0.5s', '1000ms']
    validFormats.forEach(fmt => {
      const result = MetricsSummaryCardSchema.safeParse({
        rps: 100, errorRate: '1%', p99Latency: fmt, status: 'warning',
      })
      expect(result.success).toBe(true)
    })
  })

  it('rps 不可為負數', () => {
    const result = MetricsSummaryCardSchema.safeParse({
      rps: -1, errorRate: '0%', p99Latency: '100ms', status: 'healthy',
    })
    expect(result.success).toBe(false)
  })
})

// =============================================================================
// SentryErrorCardSchema
// =============================================================================

describe('SentryErrorCardSchema', () => {
  it('合法 Props 通過驗證', () => {
    const result = SentryErrorCardSchema.safeParse({
      errorId: 'EVT-123',
      title: 'TypeError: Cannot read property',
      count: 42,
      lastSeen: '2026-03-31T10:00:00Z',
    })
    expect(result.success).toBe(true)
  })

  it('count 不可為負數 (min=0)', () => {
    const result = SentryErrorCardSchema.safeParse({
      errorId: 'x', title: 'Error', count: -1, lastSeen: '2026-01-01',
    })
    expect(result.success).toBe(false)
  })

  it('count 必須為整數', () => {
    const result = SentryErrorCardSchema.safeParse({
      errorId: 'x', title: 'Error', count: 1.5, lastSeen: '2026-01-01',
    })
    expect(result.success).toBe(false)
  })
})

// =============================================================================
// IncidentTimelineCardSchema
// =============================================================================

describe('IncidentTimelineCardSchema', () => {
  it('合法 Props 通過驗證', () => {
    const result = IncidentTimelineCardSchema.safeParse({
      incidentId: 'INC-2026-0001',
      events: [
        { timestamp: '2026-03-31T10:00:00Z', message: 'Alert fired', type: 'alert' },
        { timestamp: '2026-03-31T10:05:00Z', message: 'Acknowledged' },
      ],
      status: 'active',
    })
    expect(result.success).toBe(true)
  })

  it('空 events 陣列通過驗證', () => {
    const result = IncidentTimelineCardSchema.safeParse({
      incidentId: 'INC-001',
      events: [],
      status: 'resolved',
    })
    expect(result.success).toBe(true)
  })

  it('非法 status 不通過', () => {
    const result = IncidentTimelineCardSchema.safeParse({
      incidentId: 'INC-001',
      events: [],
      status: 'escalated',  // 不在 enum 中
    })
    expect(result.success).toBe(false)
  })
})

// =============================================================================
// K8sPodStatusCardSchema
// =============================================================================

describe('K8sPodStatusCardSchema', () => {
  it('合法 Props 通過驗證', () => {
    const result = K8sPodStatusCardSchema.safeParse({
      namespace: 'harbor',
      pods: [
        { name: 'harbor-core-xxx', status: 'Running', ready: true },
        { name: 'harbor-db-xxx', status: 'Pending' },
      ],
      summary: { total: 5, running: 4, failed: 1 },
    })
    expect(result.success).toBe(true)
  })

  it('summary.total 不可為負數', () => {
    const result = K8sPodStatusCardSchema.safeParse({
      namespace: 'ns',
      pods: [],
      summary: { total: -1, running: 0 },
    })
    expect(result.success).toBe(false)
  })
})

// =============================================================================
// TraceWaterfallCardSchema
// =============================================================================

describe('TraceWaterfallCardSchema', () => {
  it('合法 Props 通過驗證', () => {
    const result = TraceWaterfallCardSchema.safeParse({
      traceId: 'trace-abc123',
      spans: [
        { spanId: 'span-1', name: 'HTTP GET /api/v1/incidents', duration: 150, startTime: 0 },
        { spanId: 'span-2', name: 'DB query', duration: 50 },
      ],
      duration: 200,
    })
    expect(result.success).toBe(true)
  })

  it('duration 不可為負數', () => {
    const result = TraceWaterfallCardSchema.safeParse({
      traceId: 'x', spans: [], duration: -1,
    })
    expect(result.success).toBe(false)
  })
})

// =============================================================================
// NuclearKeyButtonSchema
// =============================================================================

describe('NuclearKeyButtonSchema', () => {
  it('合法 Props 通過驗證', () => {
    const result = NuclearKeyButtonSchema.safeParse({
      label: '確認執行 kubectl drain',
      riskLevel: 'critical',
      approvalId: 'APR-001',
    })
    expect(result.success).toBe(true)
  })

  it('approvalId 為選填欄位', () => {
    const result = NuclearKeyButtonSchema.safeParse({
      label: '確認',
      riskLevel: 'high',
    })
    expect(result.success).toBe(true)
  })

  it('空 label 不通過 (min_length=1)', () => {
    const result = NuclearKeyButtonSchema.safeParse({
      label: '',
      riskLevel: 'low',
    })
    expect(result.success).toBe(false)
  })

  it('NuclearKeyButton riskLevel 支援 high 與 critical', () => {
    const levels = ['low', 'medium', 'high', 'critical'] as const
    levels.forEach(level => {
      const result = NuclearKeyButtonSchema.safeParse({ label: 'test', riskLevel: level })
      expect(result.success).toBe(true)
    })
  })
})
