# Comprehensive API test script for saasadminui
# 1. Login to get token
# 2. Extract all API paths from saasadminui frontend source
# 3. Test each API against fs-company (8006)
# 4. Categorize results: 200, 404, 500, 403

$companyUrl = "http://localhost:8006"

# Step 1: Login
Write-Host "=== Step 1: Login ==="
$loginBody = '{"username":"admin","password":"admin123","tenantCode":"T202605253515"}'
$loginResp = Invoke-RestMethod -Uri "$companyUrl/login" -Method POST -ContentType "application/json" -Body $loginBody
$token = $loginResp.token
Write-Host "Login OK, token length: $($token.Length)"

$headers = @{ Authorization = "Bearer $token" }

# Step 2: Extract API paths from saasadminui frontend source
Write-Host "`n=== Step 2: Extract API paths ==="
$apiDir = "d:\ylrz\saasadminui\src\api"
$apiPaths = @{}

Get-ChildItem -Path $apiDir -Filter "*.js" -Recurse | ForEach-Object {
    $content = Get-Content $_.FullName -Raw -Encoding UTF8
    # Match patterns like: url: '/xxx/yyy' or url: "/xxx/yyy" or request({ url: '/xxx/yyy'
    $matches = [regex]::Matches($content, "[Uu][Rr][Ll]\s*[:=]\s*['""]([^'""]+)['""]")
    foreach ($m in $matches) {
        $path = $m.Groups[1].Value
        if ($path -match "^/" -and $path -notmatch "\$\{" -and $path -notmatch "^/proxy") {
            # Determine HTTP method from context
            $method = "GET"
            $lineBefore = $content.Substring(0, $m.Index)
            if ($lineBefore -match "(?m)(delete|remove|del)\s*\(" -or $path -match "/del|/remove") {
                $method = "DELETE"
            } elseif ($lineBefore -match "(?m)(add|create|save|insert|post|upload)\s*\(" -or $path -match "/add|/create|/save|/upload") {
                $method = "POST"
            } elseif ($lineBefore -match "(?m)(update|edit|modify|put)\s*\(" -or $path -match "/edit|/update") {
                $method = "PUT"
            }
            if (-not $apiPaths.ContainsKey($path)) {
                $apiPaths[$path] = $method
            }
        }
    }
}

Write-Host "Found $($apiPaths.Count) unique API paths"

# Step 3: Test each API
Write-Host "`n=== Step 3: Testing APIs ==="
$results = @{ ok = 0; notFound = 0; serverError = 0; forbidden = 0; other = 0 }
$notFoundList = @()
$serverErrorList = @()
$forbiddenList = @()
$errorDetails = @{}

$total = $apiPaths.Count
$idx = 0

foreach ($path in ($apiPaths.Keys | Sort-Object)) {
    $idx++
    $method = $apiPaths[$path]
    $url = "$companyUrl$path"
    
    try {
        if ($method -eq "GET") {
            $resp = Invoke-WebRequest -Uri $url -Headers $headers -Method GET -UseBasicParsing -TimeoutSec 10
        } elseif ($method -eq "POST") {
            $resp = Invoke-WebRequest -Uri $url -Headers $headers -Method POST -ContentType "application/json" -Body "{}" -UseBasicParsing -TimeoutSec 10
        } elseif ($method -eq "PUT") {
            $resp = Invoke-WebRequest -Uri $url -Headers $headers -Method PUT -ContentType "application/json" -Body "{}" -UseBasicParsing -TimeoutSec 10
        } elseif ($method -eq "DELETE") {
            $resp = Invoke-WebRequest -Uri $url -Headers $headers -Method DELETE -UseBasicParsing -TimeoutSec 10
        }
        
        $code = $resp.StatusCode
        $results.ok++
        
    } catch {
        $statusCode = $_.Exception.Response.StatusCode.value__
        if ($statusCode -eq 404) {
            $results.notFound++
            $notFoundList += $path
        } elseif ($statusCode -eq 500) {
            $results.serverError++
            $serverErrorList += $path
            # Get error message
            try {
                $reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream())
                $errBody = $reader.ReadToEnd()
                $reader.Close()
                if ($errBody -match '"message":"([^"]+)"') {
                    $errorDetails[$path] = $matches[1]
                } elseif ($errBody -match '"msg":"([^"]+)"') {
                    $errorDetails[$path] = $matches[1]
                }
            } catch {}
        } elseif ($statusCode -eq 403) {
            $results.forbidden++
            $forbiddenList += $path
        } else {
            $results.other++
        }
    }
    
    if ($idx % 100 -eq 0) {
        Write-Host "  Progress: $idx / $total (200=$($results.ok), 404=$($results.notFound), 500=$($results.serverError))"
    }
}

# Step 4: Output results
Write-Host "`n=== Results ==="
Write-Host "200 OK: $($results.ok)"
Write-Host "404 Not Found: $($results.notFound)"
Write-Host "500 Server Error: $($results.serverError)"
Write-Host "403 Forbidden: $($results.forbidden)"
Write-Host "Other: $($results.other)"

# Save detailed results
$notFoundList | Out-File -FilePath "d:\ylrz\saasadminui\api_404.txt" -Encoding UTF8
$serverErrorList | Out-File -FilePath "d:\ylrz\saasadminui\api_500.txt" -Encoding UTF8
$forbiddenList | Out-File -FilePath "d:\ylrz\saasadminui\api_403.txt" -Encoding UTF8

# Analyze 404 by prefix
Write-Host "`n=== 404 by prefix ==="
$notFoundByPrefix = @{}
foreach ($p in $notFoundList) {
    $parts = $p.Split("/")
    if ($parts.Length -ge 3) {
        $prefix = "/$($parts[1])/$($parts[2])"
    } elseif ($parts.Length -ge 2) {
        $prefix = "/$($parts[1])"
    } else {
        $prefix = $p
    }
    if (-not $notFoundByPrefix.ContainsKey($prefix)) { $notFoundByPrefix[$prefix] = 0 }
    $notFoundByPrefix[$prefix]++
}
$notFoundByPrefix.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 30 | ForEach-Object {
    Write-Host "  $($_.Key): $($_.Value)"
}

Write-Host "`n=== 500 by prefix ==="
$serverErrorByPrefix = @{}
foreach ($p in $serverErrorList) {
    $parts = $p.Split("/")
    if ($parts.Length -ge 3) {
        $prefix = "/$($parts[1])/$($parts[2])"
    } elseif ($parts.Length -ge 2) {
        $prefix = "/$($parts[1])"
    } else {
        $prefix = $p
    }
    if (-not $serverErrorByPrefix.ContainsKey($prefix)) { $serverErrorByPrefix[$prefix] = 0 }
    $serverErrorByPrefix[$prefix]++
}
$serverErrorByPrefix.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 30 | ForEach-Object {
    Write-Host "  $($_.Key): $($_.Value)"
}

Write-Host "`n=== 500 error details ==="
$errorDetails.GetEnumerator() | Select-Object -First 30 | ForEach-Object {
    Write-Host "  $($_.Key): $($_.Value)"
}

Write-Host "`nDone!"
