# 本地安全扫描脚本 (Windows PowerShell)
# 用法: .\scripts\security-scan.ps1
# 功能: npm audit + Trivy 文件系统扫描,输出彩色报告
# 退出码: 0=无高危漏洞, 1=存在高危漏洞

$ErrorActionPreference = "Continue"
$ProjectRoot = Resolve-Path "$PSScriptRoot\.."
Set-Location $ProjectRoot

$script:HasHigh = 0

function Write-Header($msg) {
    Write-Host "================================================" -ForegroundColor Cyan
    Write-Host "  $msg" -ForegroundColor Cyan
    Write-Host "================================================" -ForegroundColor Cyan
}
function Write-Pass($msg) { Write-Host "[PASS] $msg" -ForegroundColor Green }
function Write-Warn2($msg) { Write-Host "[WARN] $msg" -ForegroundColor Yellow }
function Write-Fail($msg) { Write-Host "[FAIL] $msg" -ForegroundColor Red; $script:HasHigh = 1 }
function Write-Info2($msg) { Write-Host "[INFO] $msg" -ForegroundColor Blue }

function Test-Command($name) {
    return [bool](Get-Command $name -ErrorAction SilentlyContinue)
}

Write-Header "本地安全扫描"
Write-Info2 "项目目录: $ProjectRoot"
Write-Host ""

# ------------------------------------------------
# 1. npm audit
# ------------------------------------------------
Write-Header "1/2 npm audit (依赖审计)"

if (-not (Test-Command "npm")) {
    Write-Fail "未检测到 npm,请先安装 Node.js"
    exit 1
}

$auditJson = "$env:TEMP\audit-report.json"
npm audit --json 2>$null | Out-File -FilePath $auditJson -Encoding utf8

if (Test-Path $auditJson) {
    try {
        $audit = Get-Content $auditJson -Raw | ConvertFrom-Json
        $v = $audit.metadata.vulnerabilities
        $critical = if ($v.critical) { [int]$v.critical } else { 0 }
        $high = if ($v.high) { [int]$v.high } else { 0 }
        $moderate = if ($v.moderate) { [int]$v.moderate } else { 0 }
        $low = if ($v.low) { [int]$v.low } else { 0 }

        Write-Host -NoNewline "  critical: "; Write-Host -NoNewline "$critical " -ForegroundColor Red
        Write-Host -NoNewline " high: "; Write-Host -NoNewline "$high " -ForegroundColor Red
        Write-Host -NoNewline " moderate: "; Write-Host -NoNewline "$moderate " -ForegroundColor Yellow
        Write-Host -NoNewline " low: "; Write-Host "$low" -ForegroundColor Green

        if ($critical -gt 0 -or $high -gt 0) {
            Write-Fail "npm audit 发现 critical/high 漏洞"
        } else {
            Write-Pass "npm audit 无 critical/high 漏洞"
        }
    } catch {
        Write-Warn2 "npm audit 报告解析失败,显示原始输出"
        npm audit --audit-level=moderate
    }

    Copy-Item $auditJson "$ProjectRoot\audit-report.json" -Force
    Write-Info2 "报告已保存: audit-report.json"
} else {
    Write-Warn2 "npm audit 未生成报告"
}
Write-Host ""

# ------------------------------------------------
# 2. Trivy 文件系统扫描
# ------------------------------------------------
Write-Header "2/2 Trivy FS Scan (文件系统扫描)"

if (-not (Test-Command "trivy")) {
    Write-Warn2 "未检测到 trivy,跳过文件系统扫描"
    Write-Info2 "安装 Trivy: https://aquasecurity.github.io/trivy/latest/getting-started/installation/"
} else {
    $trivyReport = "$ProjectRoot\trivy-fs-report.json"
    trivy fs --format json --output $trivyReport --exit-code 0 . 2>$null
    if ($LASTEXITCODE -eq 0) {
        Write-Pass "Trivy 扫描完成"
    } else {
        Write-Warn2 "Trivy 扫描返回非零状态(可能存在漏洞)"
    }

    if (Test-Path $trivyReport) {
        try {
            $trivy = Get-Content $trivyReport -Raw | ConvertFrom-Json
            $allVulns = @()
            foreach ($r in $trivy.Results) {
                if ($r.Vulnerabilities) { $allVulns += $r.Vulnerabilities }
            }
            $total = $allVulns.Count
            $critical = @($allVulns | Where-Object { $_.Severity -eq "CRITICAL" }).Count
            $high = @($allVulns | Where-Object { $_.Severity -eq "HIGH" }).Count
            $medium = @($allVulns | Where-Object { $_.Severity -eq "MEDIUM" }).Count
            $low = @($allVulns | Where-Object { $_.Severity -eq "LOW" }).Count

            Write-Host -NoNewline "  总计: $total  critical: "; Write-Host -NoNewline "$critical " -ForegroundColor Red
            Write-Host -NoNewline " high: "; Write-Host -NoNewline "$high " -ForegroundColor Red
            Write-Host -NoNewline " medium: "; Write-Host -NoNewline "$medium " -ForegroundColor Yellow
            Write-Host -NoNewline " low: "; Write-Host "$low" -ForegroundColor Green

            if ($critical -gt 0 -or $high -gt 0) {
                Write-Fail "Trivy 发现 critical/high 漏洞"
            } else {
                Write-Pass "Trivy 无 critical/high 漏洞"
            }
            Write-Info2 "报告已保存: trivy-fs-report.json"
        } catch {
            Write-Warn2 "Trivy 报告解析失败"
        }
    }

    Write-Host ""
    Write-Info2 "Trivy 表格视图:"
    trivy fs --format table --exit-code 0 .
}
Write-Host ""

# ------------------------------------------------
# 汇总
# ------------------------------------------------
Write-Header "扫描汇总"
if ($script:HasHigh -eq 0) {
    Write-Pass "未发现高危漏洞 (exit 0)"
    exit 0
} else {
    Write-Fail "发现高危漏洞,请尽快处理 (exit 1)"
    Write-Host "  SLA: critical 24h / high 7d / medium 30d / low 90d" -ForegroundColor Blue
    exit 1
}
