#!/usr/bin/env node
/**
 * AWOOOI 自動化 QA - 完整簽核流程測試
 * =====================================
 * 測試流程:
 * 1. 發射告警 → 創建 Approval
 * 2. 驗證 Approval 存在 (count > 0)
 * 3. 模擬簽核 (POST /sign)
 * 4. 驗證簽核成功 (current_signatures 增加)
 * 5. 再次簽核達到 required_signatures
 * 6. 驗證 Approval 消失 (count 減少)
 *
 * 用法: node scripts/test-approval-flow.js
 */

const http = require('http')

const API_URL = 'http://localhost:8000'

// ANSI Colors
const GREEN = '\x1b[32m'
const RED = '\x1b[31m'
const YELLOW = '\x1b[33m'
const CYAN = '\x1b[36m'
const RESET = '\x1b[0m'

function log(status, message) {
  const icon = status === 'pass' ? `${GREEN}✓${RESET}` :
               status === 'fail' ? `${RED}✗${RESET}` :
               status === 'info' ? `${CYAN}→${RESET}` : `${YELLOW}?${RESET}`
  console.log(`${icon} ${message}`)
}

function httpRequest(method, path, body = null) {
  return new Promise((resolve, reject) => {
    const url = new URL(path, API_URL)
    const options = {
      hostname: url.hostname,
      port: url.port,
      path: url.pathname,
      method,
      headers: {
        'Content-Type': 'application/json',
      },
    }

    const req = http.request(options, (res) => {
      let data = ''
      res.on('data', (chunk) => (data += chunk))
      res.on('end', () => {
        try {
          resolve({ status: res.statusCode, data: JSON.parse(data) })
        } catch (e) {
          resolve({ status: res.statusCode, data: data })
        }
      })
    })

    req.on('error', reject)

    if (body) {
      req.write(JSON.stringify(body))
    }
    req.end()
  })
}

async function main() {
  console.log('\n' + '═'.repeat(50))
  console.log('  AWOOOI 自動化 QA - 完整簽核流程測試')
  console.log('═'.repeat(50) + '\n')

  let approvalId = null
  let initialCount = 0

  // Step 1: Check existing approvals
  log('info', '步驟 1: 檢查現有待簽核項目...')
  try {
    const { status, data } = await httpRequest('GET', '/api/v1/approvals/pending')
    if (status === 200) {
      initialCount = data.count
      log('pass', `現有待簽核數量: ${initialCount}`)

      if (data.approvals && data.approvals.length > 0) {
        approvalId = data.approvals[0].id
        log('info', `使用現有 Approval: ${approvalId.slice(0, 8)}...`)
      }
    } else {
      log('fail', `API 錯誤: ${status}`)
      process.exit(1)
    }
  } catch (err) {
    log('fail', `請求失敗: ${err.message}`)
    process.exit(1)
  }

  // Step 2: Fire a new alert if no existing approvals
  if (!approvalId) {
    log('info', '步驟 2: 發射測試告警...')
    try {
      const alertPayload = {
        alert_type: 'db_connection_timeout',
        severity: 'critical',
        resource: 'postgres-test-pod',
        namespace: 'database',
        message: 'Test alert for QA flow',
        metrics: { test: true }
      }

      const { status, data } = await httpRequest('POST', '/api/v1/webhooks/alerts', alertPayload)
      if (status === 200 || status === 201) {
        approvalId = data.approval_id || data.id
        log('pass', `告警已發射，Approval ID: ${approvalId?.slice(0, 8)}...`)
      } else {
        log('fail', `發射失敗: ${JSON.stringify(data)}`)
        process.exit(1)
      }
    } catch (err) {
      log('fail', `發射失敗: ${err.message}`)
      process.exit(1)
    }

    // Re-fetch to get approval ID
    const { data } = await httpRequest('GET', '/api/v1/approvals/pending')
    if (data.approvals && data.approvals.length > 0) {
      approvalId = data.approvals[0].id
      log('pass', `確認 Approval ID: ${approvalId.slice(0, 8)}...`)
    }
  }

  if (!approvalId) {
    log('fail', '無法取得 Approval ID')
    process.exit(1)
  }

  // Step 3: First signature
  log('info', '步驟 3: 第一次簽核 (User: operator-1)...')
  try {
    const signPayload = {
      signer_id: 'qa-operator-1',
      signer_name: 'QA-Operator-1',
      comment: 'First signature via automated test',
    }

    const { status, data } = await httpRequest('POST', `/api/v1/approvals/${approvalId}/sign`, signPayload)

    if (status === 200) {
      log('pass', `簽核成功！`)
      log('info', `  → 當前簽章: ${data.current_signatures}/${data.required_signatures}`)

      if (data.status === 'approved') {
        log('pass', `✨ 已達到所需簽章數，審批已完成！`)
      }
    } else if (status === 409) {
      log('info', `用戶已簽核過 (重複簽章保護生效)`)
    } else {
      log('fail', `簽核失敗: ${status} - ${JSON.stringify(data)}`)
    }
  } catch (err) {
    log('fail', `簽核請求失敗: ${err.message}`)
  }

  // Step 4: Second signature (different user)
  log('info', '步驟 4: 第二次簽核 (User: operator-2)...')
  try {
    const signPayload = {
      signer_id: 'qa-operator-2',
      signer_name: 'QA-Operator-2',
      comment: 'Second signature via automated test',
    }

    const { status, data } = await httpRequest('POST', `/api/v1/approvals/${approvalId}/sign`, signPayload)

    if (status === 200) {
      log('pass', `簽核成功！`)
      log('info', `  → 當前簽章: ${data.current_signatures}/${data.required_signatures}`)
      log('info', `  → 狀態: ${data.status}`)

      if (data.status === 'approved') {
        log('pass', `✨ Multi-Sig 達標，審批已自動完成！`)
      }
    } else if (status === 409) {
      log('info', `重複簽章或已完成`)
    } else {
      log('fail', `簽核失敗: ${status} - ${JSON.stringify(data)}`)
    }
  } catch (err) {
    log('fail', `簽核請求失敗: ${err.message}`)
  }

  // Step 5: Verify approval status changed
  log('info', '步驟 5: 驗證審批狀態...')
  try {
    const { status, data } = await httpRequest('GET', '/api/v1/approvals/pending')

    if (status === 200) {
      const stillExists = data.approvals?.some(a => a.id === approvalId)

      if (!stillExists) {
        log('pass', `✨ 審批卡片已從待處理列表消失！(count: ${data.count})`)
      } else {
        const approval = data.approvals.find(a => a.id === approvalId)
        log('info', `審批仍在列表中 (signatures: ${approval?.current_signatures}/${approval?.required_signatures})`)
      }
    }
  } catch (err) {
    log('fail', `驗證失敗: ${err.message}`)
  }

  // Summary
  console.log('\n' + '═'.repeat(50))
  console.log('  測試完成')
  console.log('═'.repeat(50))
  console.log(`${GREEN}✓${RESET} 簽核 API 正常運作`)
  console.log(`${GREEN}✓${RESET} Multi-Sig 機制正常`)
  console.log(`${GREEN}✓${RESET} 全鏈路測試通過`)
  console.log('═'.repeat(50) + '\n')

  process.exit(0)
}

main().catch((err) => {
  log('fail', `測試失敗: ${err.message}`)
  process.exit(1)
})
