# Async Migration Analysis Script
# Scans the Jellyfin codebase for synchronous database operations that need conversion

param(
    [string]$Path = ".",
    [switch]$DetailedReport,
    [switch]$ExportCsv
)

Write-Host "🔍 Scanning for synchronous database operations..." -ForegroundColor Cyan
Write-Host ""

# Define patterns to search for
$patterns = @{
    "SaveChanges" = @{
        Pattern = "\.SaveChanges\s*\(\s*\)"
        Replacement = "await .SaveChangesAsync(cancellationToken)"
        Severity = "HIGH"
        Description = "Synchronous database save operation"
    }
    "ToList" = @{
        Pattern = "\.ToList\s*\(\s*\)"
        Replacement = "await .ToListAsync(cancellationToken)"
        Severity = "HIGH"
        Description = "Synchronous list materialization"
    }
    "ToArray" = @{
        Pattern = "\.ToArray\s*\(\s*\)"
        Replacement = "await .ToArrayAsync(cancellationToken)"
        Severity = "HIGH"
        Description = "Synchronous array materialization"
    }
    "FirstOrDefault" = @{
        Pattern = "\.FirstOrDefault\s*\("
        Replacement = 'await .FirstOrDefaultAsync('
        Severity = "HIGH"
        Description = "Synchronous first element query"
    }
    "First" = @{
        Pattern = "\.First\s*\("
        Replacement = 'await .FirstAsync('
        Severity = "HIGH"
        Description = "Synchronous first element query"
    }
    "SingleOrDefault" = @{
        Pattern = "\.SingleOrDefault\s*\("
        Replacement = 'await .SingleOrDefaultAsync('
        Severity = "MEDIUM"
        Description = "Synchronous single element query"
    }
    "Single" = @{
        Pattern = "\.Single\s*\("
        Replacement = 'await .SingleAsync('
        Severity = "MEDIUM"
        Description = "Synchronous single element query"
    }
    "Any" = @{
        Pattern = "\.Any\s*\("
        Replacement = 'await .AnyAsync('
        Severity = "MEDIUM"
        Description = "Synchronous existence check"
    }
    "Count" = @{
        Pattern = "\.Count\s*\(\s*\)"
        Replacement = "await .CountAsync(cancellationToken)"
        Severity = "MEDIUM"
        Description = "Synchronous count operation"
    }
    "LongCount" = @{
        Pattern = "\.LongCount\s*\("
        Replacement = "await .LongCountAsync("
        Severity = "MEDIUM"
        Description = "Synchronous long count operation"
    }
    "ExecuteDelete" = @{
        Pattern = "\.ExecuteDelete\s*\(\s*\)"
        Replacement = "await .ExecuteDeleteAsync(cancellationToken)"
        Severity = "HIGH"
        Description = "Synchronous bulk delete"
    }
    "ExecuteUpdate" = @{
        Pattern = "\.ExecuteUpdate\s*\("
        Replacement = "await .ExecuteUpdateAsync("
        Severity = "HIGH"
        Description = "Synchronous bulk update"
    }
    "BeginTransaction" = @{
        Pattern = "\.BeginTransaction\s*\(\s*\)"
        Replacement = "await .BeginTransactionAsync(cancellationToken)"
        Severity = "HIGH"
        Description = "Synchronous transaction start"
    }
    "Commit" = @{
        Pattern = "transaction\.Commit\s*\(\s*\)"
        Replacement = "await transaction.CommitAsync(cancellationToken)"
        Severity = "HIGH"
        Description = "Synchronous transaction commit"
    }
    "Rollback" = @{
        Pattern = "transaction\.Rollback\s*\(\s*\)"
        Replacement = "await transaction.RollbackAsync(cancellationToken)"
        Severity = "MEDIUM"
        Description = "Synchronous transaction rollback"
    }
    "Sum" = @{
        Pattern = "\.Sum\s*\("
        Replacement = 'await .SumAsync('
        Severity = "LOW"
        Description = "Synchronous sum aggregation"
    }
    "Average" = @{
        Pattern = "\.Average\s*\("
        Replacement = 'await .AverageAsync('
        Severity = "LOW"
        Description = "Synchronous average aggregation"
    }
    "Min" = @{
        Pattern = "\.Min\s*\("
        Replacement = 'await .MinAsync('
        Severity = "LOW"
        Description = "Synchronous min aggregation"
    }
    "Max" = @{
        Pattern = "\.Max\s*\("
        Replacement = 'await .MaxAsync('
        Severity = "LOW"
        Description = "Synchronous max aggregation"
    }
    "Load" = @{
        Pattern = "\.Load\s*\(\s*\)"
        Replacement = 'await .LoadAsync(cancellationToken)'
        Severity = "MEDIUM"
        Description = "Synchronous navigation property load"
    }
}

# Exclude patterns (already async or intentionally sync)
$excludePatterns = @(
    "Async\s*\(",
    "// ASYNC",
    "\.ConfigureAwait",
    "AsyncEnumerable"
)

# Get all .cs files, excluding test files and migrations initially
$files = Get-ChildItem -Path $Path -Recurse -Filter "*.cs" | 
    Where-Object { 
        $_.FullName -notmatch "\\bin\\" -and 
        $_.FullName -notmatch "\\obj\\" -and
        $_.FullName -notmatch "\\Migrations\\" -and
        $_.FullName -notmatch "\.Designer\.cs$"
    }

$results = @()
$summary = @{}

foreach ($file in $files) {
    $content = Get-Content -Path $file.FullName -Raw
    
    foreach ($patternName in $patterns.Keys) {
        $patternInfo = $patterns[$patternName]
        $pattern = $patternInfo.Pattern
        
        # Find matches
        $matches = [regex]::Matches($content, $pattern)
        
        foreach ($match in $matches) {
            # Check if this line is already async or should be excluded
            $lineStart = $content.Substring(0, $match.Index).LastIndexOf("`n")
            if ($lineStart -lt 0) { $lineStart = 0 }
            $lineEnd = $content.IndexOf("`n", $match.Index)
            if ($lineEnd -lt 0) { $lineEnd = $content.Length }
            
            $line = $content.Substring($lineStart, $lineEnd - $lineStart).Trim()
            
            # Skip if already async or excluded
            $shouldExclude = $false
            foreach ($excludePattern in $excludePatterns) {
                if ($line -match $excludePattern) {
                    $shouldExclude = $true
                    break
                }
            }
            
            if (-not $shouldExclude) {
                # Calculate line number
                $lineNumber = ($content.Substring(0, $match.Index) -split "`n").Count
                
                $result = [PSCustomObject]@{
                    File = $file.FullName.Replace($Path, "").TrimStart('\')
                    LineNumber = $lineNumber
                    Pattern = $patternName
                    Severity = $patternInfo.Severity
                    Description = $patternInfo.Description
                    MatchedText = $match.Value
                    Line = $line
                    Replacement = $patternInfo.Replacement
                }
                
                $results += $result
                
                # Update summary
                if (-not $summary.ContainsKey($patternName)) {
                    $summary[$patternName] = 0
                }
                $summary[$patternName]++
            }
        }
    }
}

# Display results
Write-Host "📊 Analysis Complete!" -ForegroundColor Green
Write-Host ""
Write-Host "=" * 80 -ForegroundColor DarkGray
Write-Host "SUMMARY" -ForegroundColor Yellow
Write-Host "=" * 80 -ForegroundColor DarkGray
Write-Host ""

$totalIssues = $results.Count
$highSeverity = ($results | Where-Object { $_.Severity -eq "HIGH" }).Count
$mediumSeverity = ($results | Where-Object { $_.Severity -eq "MEDIUM" }).Count
$lowSeverity = ($results | Where-Object { $_.Severity -eq "LOW" }).Count

Write-Host "Total synchronous operations found: " -NoNewline
Write-Host $totalIssues -ForegroundColor Red
Write-Host ""
Write-Host "  🔴 HIGH severity:   " -NoNewline
Write-Host $highSeverity -ForegroundColor Red
Write-Host "  🟡 MEDIUM severity: " -NoNewline
Write-Host $mediumSeverity -ForegroundColor Yellow
Write-Host "  🟢 LOW severity:    " -NoNewline
Write-Host $lowSeverity -ForegroundColor Green
Write-Host ""

Write-Host "Breakdown by operation type:" -ForegroundColor Cyan
Write-Host ""
$summary.GetEnumerator() | Sort-Object Value -Descending | ForEach-Object {
    $severity = $patterns[$_.Key].Severity
    $color = switch ($severity) {
        "HIGH" { "Red" }
        "MEDIUM" { "Yellow" }
        "LOW" { "Green" }
    }
    Write-Host "  $($_.Key): " -NoNewline
    Write-Host $_.Value -ForegroundColor $color -NoNewline
    Write-Host " ($severity)"
}

Write-Host ""
Write-Host "=" * 80 -ForegroundColor DarkGray

if ($DetailedReport) {
    Write-Host ""
    Write-Host "DETAILED FINDINGS" -ForegroundColor Yellow
    Write-Host "=" * 80 -ForegroundColor DarkGray
    Write-Host ""
    
    # Group by file
    $resultsByFile = $results | Group-Object -Property File
    
    foreach ($fileGroup in $resultsByFile | Sort-Object Name) {
        Write-Host ""
        Write-Host "📄 $($fileGroup.Name)" -ForegroundColor Cyan
        Write-Host "-" * 80 -ForegroundColor DarkGray
        
        foreach ($item in $fileGroup.Group | Sort-Object LineNumber) {
            $severityColor = switch ($item.Severity) {
                "HIGH" { "Red" }
                "MEDIUM" { "Yellow" }
                "LOW" { "Green" }
            }
            
            Write-Host "  Line $($item.LineNumber): " -NoNewline
            Write-Host "$($item.Pattern) " -NoNewline -ForegroundColor $severityColor
            Write-Host "- $($item.Description)"
            Write-Host "    Current:     " -NoNewline
            Write-Host $item.MatchedText -ForegroundColor Gray
            Write-Host "    Replacement: " -NoNewline
            Write-Host $item.Replacement -ForegroundColor Green
        }
    }
}

if ($ExportCsv) {
    $csvPath = Join-Path $Path "async_migration_report.csv"
    $results | Export-Csv -Path $csvPath -NoTypeInformation
    Write-Host ""
    Write-Host "📁 Report exported to: " -NoNewline
    Write-Host $csvPath -ForegroundColor Cyan
}

Write-Host ""
Write-Host "💡 TIP: Run with -DetailedReport for line-by-line analysis" -ForegroundColor DarkGray
Write-Host "💡 TIP: Run with -ExportCsv to export findings to CSV" -ForegroundColor DarkGray
Write-Host ""

# Return results for further processing
return $results
