using CodePlay.Core.Models; using CodePlay.Core.Common; namespace CodePlay.Core.Services; public interface IBatchConversionService { Task ConvertDirectoryAsync(string sourceDirectory, string targetDirectory, LanguageType sourceLanguage, LanguageType targetLanguage, ConversionOptions? options = null, CancellationToken cancellationToken = default); Task ConvertFilesAsync(IEnumerable sourceFiles, string targetDirectory, LanguageType sourceLanguage, LanguageType targetLanguage, ConversionOptions? options = null, CancellationToken cancellationToken = default); } public class BatchConversionService : IBatchConversionService { private readonly ConversionService _conversionService; private readonly IReportStorageService _reportStorageService; public BatchConversionService(ConversionService conversionService, IReportStorageService reportStorageService) { _conversionService = conversionService; _reportStorageService = reportStorageService; } public async Task ConvertDirectoryAsync(string sourceDirectory, string targetDirectory, LanguageType sourceLanguage, LanguageType targetLanguage, ConversionOptions? options = null, CancellationToken cancellationToken = default) { var result = new BatchConversionResult { SourceDirectory = sourceDirectory, TargetDirectory = targetDirectory, SourceLanguage = sourceLanguage, TargetLanguage = targetLanguage, StartedAt = DateTime.UtcNow }; if (!Directory.Exists(sourceDirectory)) { result.Success = false; result.ErrorMessage = $"Source directory not found: {sourceDirectory}"; return result; } var fileExtension = GetFileExtension(sourceLanguage); var sourceFiles = Directory.GetFiles(sourceDirectory, $"*{fileExtension}", SearchOption.AllDirectories); return await ConvertFilesAsync(sourceFiles, targetDirectory, sourceLanguage, targetLanguage, options, cancellationToken); } public async Task ConvertFilesAsync(IEnumerable sourceFiles, string targetDirectory, LanguageType sourceLanguage, LanguageType targetLanguage, ConversionOptions? options = null, CancellationToken cancellationToken = default) { var result = new BatchConversionResult { TargetDirectory = targetDirectory, SourceLanguage = sourceLanguage, TargetLanguage = targetLanguage, StartedAt = DateTime.UtcNow, TotalFiles = sourceFiles.Count() }; if (!Directory.Exists(targetDirectory)) { Directory.CreateDirectory(targetDirectory); } var targetExtension = GetFileExtension(targetLanguage); foreach (var sourceFile in sourceFiles) { if (cancellationToken.IsCancellationRequested) { result.CancelledAt = DateTime.UtcNow; break; } try { var relativePath = Path.GetRelativePath(Path.GetDirectoryName(sourceFile)!, sourceFile); var targetFileName = Path.ChangeExtension(relativePath, targetExtension); var targetFilePath = Path.Combine(targetDirectory, targetFileName); var targetFileDir = Path.GetDirectoryName(targetFilePath)!; if (!Directory.Exists(targetFileDir)) { Directory.CreateDirectory(targetFileDir); } var sourceCode = await File.ReadAllTextAsync(sourceFile, cancellationToken); var conversionResult = await _conversionService.ConvertAsync( sourceCode, sourceLanguage.ToName(), targetLanguage.ToName(), options ?? new ConversionOptions()); if (conversionResult.Success) { await File.WriteAllTextAsync(targetFilePath, conversionResult.TransformedCode, cancellationToken); result.SuccessfulFiles++; result.ConvertedFiles.Add(new ConvertedFileInfo { SourceFile = sourceFile, TargetFile = targetFilePath, LinesConverted = conversionResult.Report?.LinesConverted ?? 0, ClassesConverted = conversionResult.Report?.ClassesConverted ?? 0, MethodsConverted = conversionResult.Report?.MethodsConverted ?? 0, Warnings = conversionResult.Warnings.Count, Issues = conversionResult.Report?.Issues.Count ?? 0 }); if (conversionResult.Report != null) { conversionResult.Report.ProjectId = "batch-" + DateTime.UtcNow.ToString("yyyyMMdd"); await _reportStorageService.SaveReportAsync(conversionResult.Report); } } else { result.FailedFiles++; result.FailedFileList.Add(new FailedFileInfo { SourceFile = sourceFile, ErrorMessage = conversionResult.ErrorMessage ?? "Unknown error" }); } } catch (Exception ex) { result.FailedFiles++; result.FailedFileList.Add(new FailedFileInfo { SourceFile = sourceFile, ErrorMessage = ex.Message }); } } result.CompletedAt = DateTime.UtcNow; result.Duration = result.CompletedAt - result.StartedAt; result.Success = result.FailedFiles == 0; return result; } private string GetFileExtension(LanguageType language) { return language switch { LanguageType.CSharp => ".cs", LanguageType.Java => ".java", LanguageType.CPlusPlus => ".cpp", _ => throw new ArgumentException($"Unsupported language: {language}") }; } } public class BatchConversionResult { public bool Success { get; set; } public string? ErrorMessage { get; set; } public string SourceDirectory { get; set; } = string.Empty; public string TargetDirectory { get; set; } = string.Empty; public LanguageType SourceLanguage { get; set; } public LanguageType TargetLanguage { get; set; } public int TotalFiles { get; set; } public int SuccessfulFiles { get; set; } public int FailedFiles { get; set; } public DateTime StartedAt { get; set; } public DateTime? CompletedAt { get; set; } public DateTime? CancelledAt { get; set; } public TimeSpan? Duration { get; set; } public List ConvertedFiles { get; set; } = new(); public List FailedFileList { get; set; } = new(); } public class ConvertedFileInfo { public string SourceFile { get; set; } = string.Empty; public string TargetFile { get; set; } = string.Empty; public int LinesConverted { get; set; } public int ClassesConverted { get; set; } public int MethodsConverted { get; set; } public int Warnings { get; set; } public int Issues { get; set; } } public class FailedFileInfo { public string SourceFile { get; set; } = string.Empty; public string? TargetFile { get; set; } public string ErrorMessage { get; set; } = string.Empty; }