#!/usr/bin/env node
/**
 * AWOOOI 自動化 QA - K8s Executor 端對端測試
 * ==========================================
 * Phase 3: 驗證 K8s 執行器實際運作
 *
 * 測試流程:
 * 1. 檢查 K8s 叢集連線
 * 2. 創建/驗證 sandbox namespace
 * 3. 部署測試 Pod
 * 4. 發射告警 → 創建 Approval
 * 5. 模擬簽核 (Multi-Sig)
 * 6. 驗證 Pod 被實際重啟 (AGE 歸零)
 *
 * 用法: node scripts/test-k8s-executor.js
 */

const http = require('http')
const { execSync } = require('child_process')

const API_URL = 'http://localhost:8000'
const NAMESPACE = 'awoooi-sandbox'
const TEST_POD_NAME = 'qa-test-pod'
const KUBECONFIG = '/Users/ogt/awoooi/apps/api/k3s-prod.yaml'

// 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 kubectl(cmd) {
  try {
    return execSync(`KUBECONFIG=${KUBECONFIG} kubectl ${cmd}`, { encoding: 'utf-8', timeout: 30000 }).trim()
  } catch (err) {
    return null
  }
}

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(55))
  console.log('  AWOOOI Phase 3 QA - K8s Executor 端對端測試')
  console.log('═'.repeat(55) + '\n')

  // Step 1: Check K8s cluster connection
  log('info', '步驟 1: 檢查 K8s 叢集連線...')
  const version = kubectl('version --client -o json')
  if (version) {
    log('pass', 'kubectl 可用')
  } else {
    log('fail', 'kubectl 不可用，請確認 PATH')
    process.exit(1)
  }

  const clusterInfo = kubectl('cluster-info 2>/dev/null')
  if (clusterInfo && clusterInfo.includes('running')) {
    log('pass', 'K8s 叢集連線正常')
  } else {
    log('fail', 'K8s 叢集連線失敗')
    process.exit(1)
  }

  // Step 2: Create sandbox namespace
  log('info', `步驟 2: 創建 ${NAMESPACE} namespace...`)
  const nsExists = kubectl(`get namespace ${NAMESPACE} 2>/dev/null`)
  if (!nsExists) {
    kubectl(`create namespace ${NAMESPACE}`)
    log('pass', `Namespace ${NAMESPACE} 已創建`)
  } else {
    log('info', `Namespace ${NAMESPACE} 已存在`)
  }

  // Step 3: Deploy test pod
  log('info', '步驟 3: 部署測試 Pod...')
  const podManifest = `
apiVersion: v1
kind: Pod
metadata:
  name: ${TEST_POD_NAME}
  namespace: ${NAMESPACE}
  labels:
    app: qa-test
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
`
  // Delete existing pod first
  kubectl(`delete pod ${TEST_POD_NAME} -n ${NAMESPACE} --ignore-not-found=true`)

  // Create new pod
  try {
    execSync(`echo '${podManifest}' | KUBECONFIG=${KUBECONFIG} kubectl apply -f -`, { encoding: 'utf-8' })
    log('pass', `Pod ${TEST_POD_NAME} 已部署`)
  } catch (err) {
    log('fail', `Pod 部署失敗: ${err.message}`)
    process.exit(1)
  }

  // Wait for pod to be ready
  log('info', '等待 Pod 就緒...')
  for (let i = 0; i < 30; i++) {
    const status = kubectl(`get pod ${TEST_POD_NAME} -n ${NAMESPACE} -o jsonpath='{.status.phase}'`)
    if (status === 'Running') {
      log('pass', 'Pod 狀態: Running')
      break
    }
    await new Promise(r => setTimeout(r, 1000))
  }

  // Record initial pod creation time
  const initialCreationTime = kubectl(`get pod ${TEST_POD_NAME} -n ${NAMESPACE} -o jsonpath='{.metadata.creationTimestamp}'`)
  log('info', `初始創建時間: ${initialCreationTime}`)

  // Step 4: Fire custom alert targeting our test pod
  log('info', '步驟 4: 發射測試告警...')
  try {
    const alertPayload = {
      alert_type: 'k8s_pod_crash',
      severity: 'critical',
      source: 'awoooi-qa-test',
      target_resource: TEST_POD_NAME,
      namespace: NAMESPACE,
      message: `[QA TEST] Pod ${TEST_POD_NAME} CrashLoopBackOff - needs restart`,
      metrics: {
        restart_count: 5,
        cpu_percent: 95,
        test: true
      }
    }

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

  // Step 5: Get approval and sign it
  log('info', '步驟 5: 取得並簽核 Approval...')
  await new Promise(r => setTimeout(r, 1000))  // Wait for approval to be created

  let approvalId = null
  try {
    const { data } = await httpRequest('GET', '/api/v1/approvals/pending')
    if (data.approvals && data.approvals.length > 0) {
      approvalId = data.approvals[0].id
      log('info', `找到 Approval: ${approvalId.slice(0, 8)}...`)

      // Get required signatures
      const requiredSigs = data.approvals[0].required_signatures || 2

      // Sign with multiple users
      for (let i = 1; i <= requiredSigs; i++) {
        const signResult = await httpRequest('POST', `/api/v1/approvals/${approvalId}/sign`, {
          signer_id: `qa-signer-${i}`,
          signer_name: `QA Signer ${i}`,
          comment: `K8s executor test signature ${i}`,
        })

        if (signResult.status === 200) {
          log('pass', `簽核 ${i}/${requiredSigs} 成功`)
        } else if (signResult.status === 409) {
          log('info', `簽核 ${i} 跳過 (重複)`)
        }
      }
    } else {
      log('fail', '無待簽核項目')
    }
  } catch (err) {
    log('fail', `簽核失敗: ${err.message}`)
  }

  // Step 6: Wait and verify pod was restarted
  log('info', '步驟 6: 等待 K8s 執行器執行...')
  await new Promise(r => setTimeout(r, 5000))  // Give executor time to run

  const finalCreationTime = kubectl(`get pod ${TEST_POD_NAME} -n ${NAMESPACE} -o jsonpath='{.metadata.creationTimestamp}' 2>/dev/null`)

  console.log('\n' + '─'.repeat(55))
  console.log('  驗證結果')
  console.log('─'.repeat(55))

  if (!finalCreationTime) {
    log('info', 'Pod 已被刪除 (executor 執行 delete pod)')
    log('pass', '✨ K8s Executor 執行成功！')
  } else if (finalCreationTime !== initialCreationTime) {
    log('pass', `Pod 創建時間已更新: ${finalCreationTime}`)
    log('pass', '✨ K8s Executor 執行成功！(Pod 重啟)')
  } else {
    log('info', `Pod 創建時間未變: ${finalCreationTime}`)
    log('info', '可能原因: 執行器正在處理或 kubeconfig 權限問題')

    // Check API logs for execution status
    log('info', '檢查後端日誌...')
  }

  // Cleanup
  log('info', '清理測試資源...')
  kubectl(`delete pod ${TEST_POD_NAME} -n ${NAMESPACE} --ignore-not-found=true`)

  console.log('\n' + '═'.repeat(55))
  console.log('  Phase 3 K8s Executor 測試完成')
  console.log('═'.repeat(55) + '\n')
}

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