๐Ÿ“„ reporter.ts  โ€ข  4690 bytes
/**
 * ้ชŒ่ฏ็ณป็ปŸ - ๆŠฅๅ‘Š็”Ÿๆˆ
 * Phase 3: ้ชŒ่ฏๆŠฅๅ‘Š
 */
import { 
  type VerificationReport, 
  type VerificationResult, 
  type VerificationIssue,
  type VerificationOptions 
} from './types'
import { STATUS_LABELS, TYPE_LABELS } from './types'

/** ็”Ÿๆˆๅ”ฏไธ€ID */
function generateId(): string {
  return 'vr_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 6)
}

/**
 * ๅˆ›ๅปบ้ชŒ่ฏๆŠฅๅ‘Š
 */
export function createReport(file: string): VerificationReport {
  return {
    id: generateId(),
    file,
    timestamp: new Date().toISOString(),
    results: [],
    overallPassed: true,
    summary: {
      total: 0,
      passed: 0,
      failed: 0,
      warnings: 0,
    },
  }
}

/**
 * ๆทปๅŠ ้ชŒ่ฏ็ป“ๆžœๅˆฐๆŠฅๅ‘Š
 */
export function addResult(
  report: VerificationReport,
  result: VerificationResult
): void {
  report.results.push(result)
  
  // ๆ›ดๆ–ฐๆ‘˜่ฆ
  report.summary.total++
  if (result.passed) {
    report.summary.passed++
  } else {
    report.summary.failed++
  }
  report.summary.warnings += result.issues.filter(i => i.type === 'warning').length
  
  // ๆ›ดๆ–ฐๆ•ดไฝ“็Šถๆ€
  if (!result.passed) {
    report.overallPassed = false
  }
}

/**
 * ๆ ผๅผๅŒ–้ชŒ่ฏๆŠฅๅ‘Šไธบๆ–‡ๆœฌ
 */
export function formatReport(report: VerificationReport): string {
  let output = '\n'
  output += '  โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—\n'
  output += `  โ•‘  ๐Ÿ” ้ชŒ่ฏๆŠฅๅ‘Š: ${report.file.padEnd(30)}โ•‘\n`
  output += '  โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•\n\n'
  
  output += `  ๐Ÿ“ ๆ–‡ไปถ: ${report.file}\n`
  output += `  โฑ๏ธ  ๆ—ถ้—ด: ${new Date(report.timestamp).toLocaleString()}\n\n`
  
  output += '  โ”€โ”€โ”€โ”€ ้ชŒ่ฏ็ป“ๆžœ โ”€โ”€โ”€โ”€\n\n'
  
  for (const result of report.results) {
    const label = TYPE_LABELS[result.type]
    const status = STATUS_LABELS[result.status]
    const icon = result.passed ? 'โœ…' : 'โŒ'
    
    output += `  ${icon} ${label}\n`
    output += `     ็Šถๆ€: ${status}\n`
    output += `     ่€—ๆ—ถ: ${result.duration}ms\n`
    
    if (result.issues.length > 0) {
      output += '     ้—ฎ้ข˜:\n'
      for (const issue of result.issues) {
        const typeIcon = issue.type === 'error' ? 'โŒ' : issue.type === 'warning' ? 'โš ๏ธ' : 'โ„น๏ธ'
        output += `       ${typeIcon} ${issue.message}\n`
        if (issue.location) {
          output += `          ไฝ็ฝฎ: ${issue.location.file}`
          if (issue.location.line) {
            output += `:${issue.location.line}`
          }
          output += '\n'
        }
        if (issue.suggestion) {
          output += `          ๅปบ่ฎฎ: ${issue.suggestion}\n`
        }
      }
    }
    
    output += '\n'
  }
  
  output += '  โ”€โ”€โ”€โ”€ ๆ‘˜่ฆ โ”€โ”€โ”€โ”€\n\n'
  output += `  ๐Ÿ“Š ๆ€ป่ฎก: ${report.summary.total}\n`
  output += `  โœ… ้€š่ฟ‡: ${report.summary.passed}\n`
  if (report.summary.failed > 0) {
    output += `  โŒ ๅคฑ่ดฅ: ${report.summary.failed}\n`
  }
  if (report.summary.warnings > 0) {
    output += `  โš ๏ธ  ่ญฆๅ‘Š: ${report.summary.warnings}\n`
  }
  output += '\n'
  
  const overallIcon = report.overallPassed ? 'โœ…' : 'โŒ'
  output += `  ${overallIcon} ๆ•ดไฝ“็ป“ๆžœ: ${report.overallPassed ? '้€š่ฟ‡' : 'ๆœช้€š่ฟ‡'}\n`
  
  return output
}

/**
 * ๆ ผๅผๅŒ–็ฎ€ๅ•ๆ‘˜่ฆ
 */
export function formatSummary(report: VerificationReport): string {
  const icon = report.overallPassed ? 'โœ…' : 'โŒ'
  const passed = report.summary.passed
  const total = report.summary.total
  const failed = report.summary.failed
  const warnings = report.summary.warnings
  
  let summary = `${icon} ้ชŒ่ฏ ${passed}/${total}`
  
  if (failed > 0) {
    summary += ` | โŒ ${failed} ้กนๅคฑ่ดฅ`
  }
  
  if (warnings > 0) {
    summary += ` | โš ๏ธ ${warnings} ้กน่ญฆๅ‘Š`
  }
  
  return summary
}

/**
 * ่Žทๅ–ๅคฑ่ดฅ็š„้—ฎ้ข˜ๅˆ—่กจ
 */
export function getFailedIssues(report: VerificationReport): VerificationIssue[] {
  const issues: VerificationIssue[] = []
  
  for (const result of report.results) {
    if (!result.passed) {
      issues.push(...result.issues.filter(i => i.type === 'error'))
    }
  }
  
  return issues
}

/**
 * ๆฃ€ๆŸฅๆ˜ฏๅฆ้œ€่ฆๅคฑ่ดฅ
 */
export function shouldFail(
  report: VerificationReport,
  options: VerificationOptions
): boolean {
  // ๅฆ‚ๆžœๆœ‰ไปปไฝ•้ชŒ่ฏๅคฑ่ดฅ
  if (report.summary.failed > 0) {
    return true
  }
  
  // ๆฃ€ๆŸฅ่ญฆๅ‘Šๆ˜ฏๅฆๅฏผ่‡ดๅคฑ่ดฅ
  if (options.failOnWarning && report.summary.warnings > 0) {
    return true
  }
  
  return false
}