Repository: JinoSejera/THESSA
Pull request #3: Working API need to refactor.
Author: login: JinoSejera
Created: 2025-05-26T04:12:18Z | Merged: 2025-05-27T10:38:39Z



Diff:
diff --git a/Contract/IGit.cs b/Contract/IGit.cs
deleted file mode 100644
index 10c0552..0000000
--- a/Contract/IGit.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-﻿namespace THESSA.Contract;
-
-public interface IGit
-{
-    string GetRemoteName();
-    string GetLastCommitSha(string file);
-    List<string> GetDiffFiles(string remoteName, string headRef, string baseRef);
-    string GetDiffInFile(string remoteName, string headRef, string baseRef, string filePath);
-
-}
diff --git a/Contract/IGitHub.cs b/Contract/IGitHub.cs
index 1fe9986..3c9de9c 100644
--- a/Contract/IGitHub.cs
+++ b/Contract/IGitHub.cs
@@ -6,5 +6,7 @@ public interface IGitHub
     {
         Task <string?> PostCommentToLineAsync(string token, PostCommentToLineRequestBody requestBody, RepositoryMetadata repoMetadata);
         Task <string?> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData);
+        Task<List<FileData>> GetDiffFilesAsync(string token, RepositoryMetadata repoMetadata);
+        Task<string> GetFileContentAsync(string token, string fileUrl);
     }
 }
diff --git a/Contract/IGithubService.cs b/Contract/IGithubService.cs
index 34fd51b..c9fd7e1 100644
--- a/Contract/IGithubService.cs
+++ b/Contract/IGithubService.cs
@@ -4,7 +4,11 @@ namespace THESSA.Contract
 {
     public interface IGithubService
     {
-        Task<string?> PostCommentToLineAsync(string token, PostCommentToLineRequestBody requestBody, RepositoryMetadata repoMetadata);
-        Task<string?> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData);
+        Task<bool> PostCommentToLineAsync(string token, string message, string commitId, string filePath, int position, RepositoryMetadata repoMetadata);
+        Task<bool> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData);
+        Task<List<FileData>> GetFilesDiffAsync(string token, RepositoryMetadata repoMetadata);
+        Task<string> GetFileContentAsync(string token, string fileUrl);
+
+
     }
 }
diff --git a/Contract/IThessaBotRepository.cs b/Contract/IThessaBotRepository.cs
index 84144ed..bc264cc 100644
--- a/Contract/IThessaBotRepository.cs
+++ b/Contract/IThessaBotRepository.cs
@@ -5,55 +5,8 @@ namespace THESSA.Contract
     public interface IThessaBotRepository
     {
         Task<string> RequestDiffs(string code, string diff);
+        List<LineComment> SplitThessaReview(string response);
+        bool IsNoIssueText(string source);
 
-        private static readonly string NoResponse = "No critical issues found";
-        private static readonly string Problems = "errors, issues, potential crashes or unhandled exceptions";
-        private static readonly string ThessQuery = @"
-# TASK
-Could you describe briefly {0}, for the next code with the given git diffs?
-Please, also do not add introduction words, just print errors in the format: ""line_number: cause effect""
-If there are no {0} just say ""{1}"".
-
-## DIFFS:
-{2}
-
-## Full code from the file:
-{3}
-";
-        static string BuilThessQuery(string code, string diffs) =>
-            string.Format(ThessQuery, Problems, NoResponse, diffs, code);
-
-        static bool IsNoIssueText(string source)
-        {
-            var target = NoResponse.Replace(" ", "");
-            var sourceNoSpaces = source.Replace(" ", "");
-            return sourceNoSpaces.StartsWith(target);
-        }
-
-        static List<LineComment> SplitThessResponse(string response)
-        {
-            var result = new List<LineComment>();
-            if(string.IsNullOrEmpty(response)) return result;
-
-            var lines = response.Trim().Split('\n');
-            foreach (var fullRawText in lines)
-            {
-                var fullText = fullRawText.Trim();
-                if (fullText.Length == 0) continue;
-
-                string numberStr = "";
-                foreach (var ch in fullText)
-                {
-                    if (char.IsDigit(ch)) numberStr += ch;
-                    else break;
-                }
-
-                int number = 0;
-                if (!string.IsNullOrEmpty(numberStr)) int.TryParse(numberStr, out number);
-
-                result.Add(new LineComment { Line = number, Comment = fullText});
-            }
-            return result;
-        }
     }
 }
diff --git a/Contract/IThessaService.cs b/Contract/IThessaService.cs
new file mode 100644
index 0000000..531f90d
--- /dev/null
+++ b/Contract/IThessaService.cs
@@ -0,0 +1,11 @@
+﻿using THESSA.Models;
+
+namespace THESSA.Contract
+{
+    public interface IThessaService
+    {
+        Task<string> ReviewAsync(string code, string diff);
+        List<LineComment> SplitReview(string response);
+        bool IsNoIssueText(string source);
+    }
+}
diff --git a/Controllers/GitHubController.cs b/Controllers/GitHubController.cs
index 97b1474..c14872b 100644
--- a/Controllers/GitHubController.cs
+++ b/Controllers/GitHubController.cs
@@ -1,8 +1,12 @@
 ﻿using System.Text.Json;
+using System.Threading.Tasks;
 using Asp.Versioning;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
+using THESSA.Contract;
+using THESSA.Helper;
 using THESSA.Models;
+using THESSA.Repository;
 
 namespace THESSA.Controllers
 {
@@ -13,13 +17,21 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
@@ -27,11 +39,109 @@ public IActionResult PostReview(
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
+
+                await Task.WhenAll(contentTasks);
+
+                foreach (var file in changedFiles)
+                {
+                    // Checking if file extension of file to review is supported
+                    var fileExtension = Path.GetExtension(file.FileName);
+                    if (!extensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase))
+                    {
+                        _logger.LogWarning($"Skipping, unsupported extension: {fileExtension} file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Checking if File content is empty
+                    if (file.Content!.Length == 0)
+                    {
+                        _logger.LogWarning($"Skipping, empty content for file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Check if File Diff is Empty
+                    if (file.Patch!.Length == 0)
+                        _logger.LogWarning($"diff for file: {file.FileName} is Empty");
+
+                    string separator = "\n\n----------------------------------------------------------------------\n\n";
+                    _logger.LogInformation($"Asking Review for THESSA AI... Content Length: {file.Content.Length} Diff Length: {file.Patch.Length}.");
+
+                    var thessaReview = await _thessaService.ReviewAsync(file.Content, file.Patch);
+
+                    _logger.LogInformation($"{separator}{file.Content}{separator}{file.Patch}{separator}{thessaReview}{separator}");
+
+                    if (_thessaService.IsNoIssueText(thessaReview))
+                        _logger.LogInformation($"File: {file.FileName} looks good. Continue.");
+                    else
+                    {
+                        var lineComments = _thessaService.SplitReview(thessaReview);
+
+                        if (lineComments.Count == 0)
+                        {
+                            _logger.LogWarning($"No comments found for file: {file.FileName}");
+                        }
+
+                        bool reviewResult = false;
+                        foreach (var lineComment in lineComments)
+                        {
+                            try
+                            {
+                                if (lineComment.Line != null)
+                                    reviewResult = await _gitHubService.PostCommentToLineAsync(
+                                        metadata.Token, 
+                                        lineComment.Comment!, 
+                                        file.CommitId!, 
+                                        file.FileName!, 
+                                        lineComment.Line, 
+                                        repositoryRequestMetaData);
+                                if (!reviewResult)
+                                    reviewResult = await _gitHubService.PostGeneralCommentAsync(lineComment.Comment!, metadata.Token, repositoryRequestMetaData);
+                            }
+                            catch (Exception ex)
+                            {
+                                _logger.LogError(ex, $"Error posting comment for file: {file.FileName} at line: {lineComment.Line}");
+                                throw new RepositoryException("Failed to post any Review.", ex);
+                            }
+                        }
+                    }
+                }
+                return Ok("Succeed");
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Error processing GitHub request");
+                return StatusCode(StatusCodes.Status500InternalServerError, "An error occurred while processing the request.");
+            }
         }
     }
 }
diff --git a/Helper/Git.cs b/Helper/Git.cs
deleted file mode 100644
index 6eaf35e..0000000
--- a/Helper/Git.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-﻿using System.Net.Http;
-using System.Net.Http.Headers;
-using System.Text.Json;
-using THESSA.Contract;
-
-namespace THESSA.Helper
-{
-    public class Git : IGit
-    {
-        private readonly ILogger<Git> _logger;
-        private readonly HttpClient _httpClient;
-        private readonly string _owner;
-        private readonly string _repo;
-
-        public Git(ILogger<Git> logger, HttpClient httpClient, string owner, string repo, string githubToken)
-        {
-            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
-            _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
-            _owner = owner;
-            _repo = repo;
-            _httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THESSA", "1.0"));
-            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("token", githubToken);
-        }
-
-        public string GetRemoteName()
-        {
-            // Not directly available via GitHub API; return repo name as remote name
-            return _repo;
-        }
-
-        public string GetLastCommitSha(string file)
-        {
-            var url = $"https://api.github.com/repos/{_owner}/{_repo}/commits?path={Uri.EscapeDataString(file)}&per_page=1";
-            var response = _httpClient.GetAsync(url).Result;
-            response.EnsureSuccessStatusCode();
-            var json = response.Content.ReadAsStringAsync().Result;
-            using var doc = JsonDocument.Parse(json);
-            var sha = doc.RootElement[0].GetProperty("sha").GetString();
-            return sha!;
-        }
-
-        public List<string> GetDiffFiles(string remoteName, string headRef, string baseRef)
-        {
-            var url = $"https://api.github.com/repos/{_owner}/{_repo}/compare/{baseRef}...{headRef}";
-            var response = _httpClient.GetAsync(url).Result;
-            response.EnsureSuccessStatusCode();
-            var json = response.Content.ReadAsStringAsync().Result;
-            using var doc = JsonDocument.Parse(json);
-            var files = doc.RootElement.GetProperty("files");
-            var result = new List<string>();
-            foreach (var file in files.EnumerateArray())
-            {
-                result.Add(file.GetProperty("filename").GetString()!);
-            }
-            return result;
-        }
-
-        public string GetDiffInFile(string remoteName, string headRef, string baseRef, string filePath)
-        {
-            var url = $"https://api.github.com/repos/{_owner}/{_repo}/compare/{baseRef}...{headRef}";
-            var response = _httpClient.GetAsync(url).Result;
-            response.EnsureSuccessStatusCode();
-            var json = response.Content.ReadAsStringAsync().Result;
-            using var doc = JsonDocument.Parse(json);
-            var files = doc.RootElement.GetProperty("files");
-            foreach (var file in files.EnumerateArray())
-            {
-                if (file.GetProperty("filename").GetString() == filePath)
-                {
-                    return file.GetProperty("patch").GetString() ?? "";
-                }
-            }
-            return "";
-        }
-    }
-
-}
diff --git a/Helper/Utils.cs b/Helper/Utils.cs
new file mode 100644
index 0000000..e906050
--- /dev/null
+++ b/Helper/Utils.cs
@@ -0,0 +1,30 @@
+﻿using System.Text;
+
+namespace THESSA.Helper;
+
+public static class Utils
+{
+    public static string DecodeContentBase64(string content)
+    {
+        if (string.IsNullOrWhiteSpace(content)) 
+            throw new ArgumentNullException("Content cannot be null or Empty", nameof(content));
+
+        // Normalize by Removing escape characters and trimming whitespaces
+
+        var normalize = content
+            .Replace("\n", "")
+            .Replace("\r", "")
+            .Replace("\\n", "")
+            .Trim();
+
+        try
+        {
+            byte[] data = Convert.FromBase64String(normalize);
+            return Encoding.UTF8.GetString(data);
+        }
+        catch (Exception ex)
+        {
+            throw new ArgumentException("Content is not a valid Base64 string", ex);
+        }
+    }
+}
diff --git a/KernelExtension.cs b/KernelExtension.cs
index 59b8637..6cfa4ba 100644
--- a/KernelExtension.cs
+++ b/KernelExtension.cs
@@ -1,4 +1,6 @@
-﻿using Microsoft.SemanticKernel;
+﻿using System.ClientModel;
+using Azure.AI.OpenAI;
+using Microsoft.SemanticKernel;
 
 namespace Extensions;
 
@@ -13,12 +15,28 @@ public static void AddKernelServices(this IServiceCollection services)
             {
                 var config = sp.GetRequiredService<IConfiguration>();
                 IKernelBuilder builder = Kernel.CreateBuilder();
+
+                var endPoint = config["AZURE_OPENAI_ENDPOINT"] ?? throw new ArgumentNullException("Azure OpenAI Endpoint not set.");
+                var deployment = config["AZURE_OPENAI_DEPLOYMENT_NAME"] ?? throw new ArgumentNullException("Azure OpenAI Deployment name not set.");
+                var apiKey = config["AZURE_OPENAI_API_KEY"] ?? throw new ArgumentNullException("Azure OpenAI API Key not set.");
+                var apiVersion = config["AZURE_OPENAI_API_VERSION"] ?? "2025-01-01-preview";
+
+                var client = new AzureOpenAIClient(
+                    endpoint: new Uri(endPoint),
+                    credential: new ApiKeyCredential(apiKey));
+
+                //builder.AddAzureOpenAIChatCompletion(
+                //    serviceId: "THESS",
+                //    deploymentName: config["AZURE_OPENAI_DEPLOYMENT_NAME"] ?? throw new ArgumentNullException("Azure OpenAI Deployment name not set."),
+                //    endpoint: config["AZURE_OPENAI_ENDPOINT"] ?? throw new ArgumentNullException("Azure OpenAI Endpoint not set."),
+                //    apiKey: config["AZURE_OPENAI_API_KEY"] ?? throw new ArgumentNullException("Azure OpenAI API Key not set."),
+                //    apiVersion: config["AZURE_OPENAI_API_VERSION"] ?? "2025-01-01-preview"
+                //    );
+
                 builder.AddAzureOpenAIChatCompletion(
                     serviceId: "THESS",
-                    deploymentName: config["AZURE_OPENAI_DEPLOYMENT_NAME"] ?? throw new ArgumentNullException("Azure OpenAI Deployment name not set."),
-                    endpoint: config["AZURE_OPENAI_ENDPOINT"] ?? throw new ArgumentNullException("Azure OpenAI Endpoint not set."),
-                    apiKey: config["AZURE_OPENAI_API_KEY"] ?? throw new ArgumentNullException("Azure OpenAI API Key not set."),
-                    apiVersion: config["AZURE_OPENAI_API_VERSION"] ?? "2025-01-01-preview"
+                    azureOpenAIClient: client,
+                    deploymentName: deployment
                     );
 
                 var kernel = builder.Build();
diff --git a/Models/FileData.cs b/Models/FileData.cs
new file mode 100644
index 0000000..03f9611
--- /dev/null
+++ b/Models/FileData.cs
@@ -0,0 +1,12 @@
+﻿namespace THESSA.Models
+{
+    public class FileData
+    {
+        public string? FileName { get; set; }
+        public string? ContentUrl { get; set; }
+        public string? Patch { get; set; }
+        public string? CommitId { get; set; }
+        public string? Content { get; set; } = string.Empty;
+
+    }
+}
diff --git a/Models/GitHubRequestBody.cs b/Models/GitHubRequestBody.cs
index 7b10a7d..b88dfbd 100644
--- a/Models/GitHubRequestBody.cs
+++ b/Models/GitHubRequestBody.cs
@@ -14,6 +14,6 @@ public class GitHubRequestBody
         public string RepositoryOwner { get; set; }
 
         [Required]
-        public string CommitId { get; set; }
+        public string? CommitId { get; set; }
     }
 }
diff --git a/Models/PostCommentToLineRequestBody.cs b/Models/PostCommentToLineRequestBody.cs
index cf23bfa..2215e15 100644
--- a/Models/PostCommentToLineRequestBody.cs
+++ b/Models/PostCommentToLineRequestBody.cs
@@ -3,7 +3,7 @@
     public class PostCommentToLineRequestBody
     {
         public string? body { get; set; }
-        public int commit_id { get; set; }
+        public string? commit_id { get; set; }
         public string? path { get; set; }
         public int position { get; set; }
     }
diff --git a/Plugins/CommentGenerator/PullRequestCommentGen/config.json b/Plugins/CommentGenerator/PullRequestCommentGen/config.json
index 563ee10..4d912b9 100644
--- a/Plugins/CommentGenerator/PullRequestCommentGen/config.json
+++ b/Plugins/CommentGenerator/PullRequestCommentGen/config.json
@@ -3,34 +3,33 @@
     "description": "Generate Comment Review on Pull Request",
     "execution_settings": {
         "default": {
-            "max_tokens": 150,
-            "temperature": 0.9,
-            "top_p": 0.1,
-            "presence_penalty": 0.6,
-            "frequency_penalty": 0.1
+            "max_tokens": 1000,
+            "temperature": 0.2,
+            "top_p": 0.5,
+            "presence_penalty": 0.0,
+            "frequency_penalty": 0.0
+        }
+    },
+    "input_variables": [
+        {
+            "name": "code",
+            "description": "source code",
+            "default": ""
         },
-        "input_variables": [
-            {
-                "name": "code",
-                "description": "source code",
-                "default": ""
-            },
-            {
-                "name": "diffs",
-                "description": "the differences between two versions of source code.",
-                "default": ""
-            },
-            {
-                "name": "no_response",
-                "description": "No Response Message.",
-                "default": "No critical issues found"
-            },
-            {
-                "name": "problems",
-                "description": "Error, issues and potential crashes or unhandled exceptions.",
-                "default": "errors, issues, potential crashes or unhandled exceptions"
-            }
-
-        ]
-    }
+        {
+            "name": "diffs",
+            "description": "the differences between two versions of source code.",
+            "default": ""
+        },
+        {
+            "name": "no_response",
+            "description": "No Response Message.",
+            "default": "No critical issues found"
+        },
+        {
+            "name": "problems",
+            "description": "Error, issues and potential crashes or unhandled exceptions.",
+            "default": "errors, issues, potential crashes or unhandled exceptions"
+        }
+    ]
 }
\ No newline at end of file
diff --git a/Plugins/CommentGenerator/PullRequestCommentGen/skprompt.txt b/Plugins/CommentGenerator/PullRequestCommentGen/skprompt.txt
index 91d50d3..57a79f9 100644
--- a/Plugins/CommentGenerator/PullRequestCommentGen/skprompt.txt
+++ b/Plugins/CommentGenerator/PullRequestCommentGen/skprompt.txt
@@ -1,7 +1,7 @@
 ﻿# TASK
-Could you describe briefly {0}, for the next code with the given git diffs?
+Could you describe briefly {{$problems}}, for the next code with the given git diffs?
 Please, also do not add introduction words, just print errors in the format: ""line_number: cause effect""
-If there are no {{$no_response}} just say ""{{$problems}}"".
+If there are no {{$problems}} just say ""{{$no_response}}"".
 
 ## DIFFS:
 {{$diffs}}
diff --git a/Program.cs b/Program.cs
index 45bec21..618d062 100644
--- a/Program.cs
+++ b/Program.cs
@@ -1,6 +1,7 @@
 using Extensions;
 using THESSA.Contract;
 using THESSA.Repository;
+using THESSA.Services;
 
 var builder = WebApplication.CreateBuilder(args);
 
@@ -17,7 +18,14 @@
 // Register Semantic Kernel
 builder.Services.AddKernelServices();
 
+// Register Repositories
 builder.Services.AddScoped<IThessaBotRepository, ThessaRepository>();
+builder.Services.AddScoped<IGitHub, GitHubRepository>();
+
+// Register Services
+builder.Services.AddScoped<IGithubService, GitHubService>();
+builder.Services.AddScoped<IThessaService, ThessaService>();
+
 var app = builder.Build();
 
 // Configure the HTTP request pipeline.
diff --git a/Repository/GitHubRepository.cs b/Repository/GitHubRepository.cs
index 3722ba5..d9eb248 100644
--- a/Repository/GitHubRepository.cs
+++ b/Repository/GitHubRepository.cs
@@ -3,6 +3,7 @@
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
+using System.Web;
 using THESSA.Contract;
 using THESSA.Models;
 
@@ -22,7 +23,9 @@ public GitHubRepository(HttpClient httpClient)
         {
             SetGitHubHeaders(token);
             string url = GetAddCommentURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
-            return await PostJsonAsync(url, requestBody, "line comment");
+            var response = await PostJsonAsync(url, requestBody, "line comment");
+
+            return await response.Content.ReadAsStringAsync();
         }
 
         public async Task<string?> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData)
@@ -30,7 +33,72 @@ public GitHubRepository(HttpClient httpClient)
             SetGitHubHeaders(token);
             var body = new { body = text };
             string url = GetAddIssueURL(repoMetaData.RepositoryOwner!, repoMetaData.RepositoryName!, repoMetaData.PullRequestNumber);
-            return await PostJsonAsync(url, body, "general comment");
+            var response = await PostJsonAsync(url, body, "general comment");
+
+            return await response.Content.ReadAsStringAsync();
+        }
+
+        public async Task<List<FileData>> GetDiffFilesAsync(string token, RepositoryMetadata repoMetadata)
+        {
+            SetGitHubHeaders(token);
+            string url = GetFileListURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
+            var response = await GetJsonAsync(url);
+            var json = await response.Content.ReadAsStringAsync();
+
+            var result = new List<FileData>();
+            using (var doc = JsonDocument.Parse(json))
+            {
+                foreach (var element in doc.RootElement.EnumerateArray())
+                {
+                    if (element.TryGetProperty("contents_url", out var contentsUrlProp) && element.TryGetProperty("filename", out var filenameProp) && element.TryGetProperty("patch", out var patchProp))
+                    {
+                        var fileData = new FileData();
+                        var contentsUrl = contentsUrlProp.GetString();
+                        var filename = filenameProp.GetString();
+                        var patch = patchProp.GetString();
+                        if (!string.IsNullOrEmpty(contentsUrl))
+                        {
+                            fileData.ContentUrl = contentsUrl;
+
+                            Uri contentUri = new Uri(contentsUrl);
+                            string query = contentUri.Query;
+
+                            var queryParams = HttpUtility.ParseQueryString(query);
+                            fileData.CommitId = queryParams["ref"];
+                        }
+                        if (!string.IsNullOrEmpty(filename))
+                        {
+                            fileData.FileName = filename;
+                        }
+                        if (!string.IsNullOrEmpty(patch))
+                        {
+                            fileData.Patch = patch;
+                        }
+                        result.Add(fileData);
+                    }
+                }
+            }
+            return result;
+        }
+
+        public async Task<string> GetFileContentAsync(string token, string fileUrl)
+        {
+            SetGitHubHeaders(token);
+            var response = await GetJsonAsync(fileUrl);
+            var json = await response.Content.ReadAsStringAsync();
+
+            using(var doc = JsonDocument.Parse(json))
+            {
+                if (doc.RootElement.TryGetProperty("content", out var contentProp))
+                {
+                    return contentProp.GetString()!;
+                }
+                else
+                {
+                    throw new RepositoryException("Invalid response format: 'content' not found");
+                }
+            }
+
         }
 
         private void SetGitHubHeaders(string token)
@@ -42,13 +110,13 @@ private void SetGitHubHeaders(string token)
             }
         }
 
-        private async Task<string?> PostJsonAsync(string url, object body, string errorContext)
+        private async Task<HttpResponseMessage> PostJsonAsync(string url, object body, string errorContext)
         {
             var content = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
             var response = await _httpClient.PostAsync(url, content);
             if (response.IsSuccessStatusCode)
             {
-                return await response.Content.ReadAsStringAsync();
+                return response;
             }
             else
             {
@@ -56,6 +124,25 @@ private void SetGitHubHeaders(string token)
             }
         }
 
+        private async Task<HttpResponseMessage> GetJsonAsync(string url)
+        {
+            var response = await _httpClient.GetAsync(url);
+            if (response.IsSuccessStatusCode)
+            {
+                return response;
+            }
+            else
+            {
+                throw new RepositoryException($"Error fetching data from {url} - Status Code: {response.StatusCode}");
+            }
+
+        }
+
+        private string GetFileListURL(string repoOwner, string repoName, int pullNumber)
+        {
+            return $"https://api.github.com/repos/{repoOwner}/{repoName}/pulls/{pullNumber}/files";
+        }
+
         private string GetAddCommentURL(string repoOwner, string repoName, int pullNumber)
         {
             return $"https://api.github.com/repos/{repoOwner}/{repoName}/pulls/{pullNumber}/comments";
diff --git a/Repository/ThessaRepository.cs b/Repository/ThessaRepository.cs
index 0b1d5c5..bc56764 100644
--- a/Repository/ThessaRepository.cs
+++ b/Repository/ThessaRepository.cs
@@ -1,31 +1,66 @@
 ﻿using Microsoft.SemanticKernel;
 using THESSA.Contract;
+using THESSA.Models;
 
 namespace THESSA.Repository;
 
 public class ThessaRepository : IThessaBotRepository
 {
     private readonly Kernel _kernel;
-
     public ThessaRepository(Kernel kernel)
     {
         _kernel = kernel ?? throw new ArgumentNullException(nameof(kernel));
     }
 
-    public async Task<string> RequestDiffs(string code, string diff)
+    public bool IsNoIssueText(string source)
     {
-        string[] content = [];
+        var target = "No critical issues found".Replace(" ", "");
+        var sourceNoSpaces = source.Replace(" ", "");
+        return sourceNoSpaces.StartsWith(target);
+    }
 
-        var arguments = new KernelArguments() { ["code"] = code, ["diffs"] = diff
-        };
+    public async Task<string> RequestDiffs(string code, string diff)
+    {
+        var sb = new System.Text.StringBuilder();
 
-        var result = _kernel.InvokeStreamingAsync("CommentGenerator", "PullRequestCOmmentGen", arguments);
+        var arguments = new KernelArguments() { ["code"] = code, ["diffs"] = diff };
 
         await foreach (StreamingKernelContent response in _kernel.InvokeStreamingAsync("CommentGenerator", "PullRequestCOmmentGen", arguments))
         {
-            content.Append(response.ToString());
+            sb.Append(response.ToString());
+        }
+
+        return sb.ToString().Trim();
+    }
+
+    public List<LineComment> SplitThessaReview(string response)
+    {
+        var lineComments = new List<LineComment>();
+        if (string.IsNullOrEmpty(response)) return lineComments;
+
+        var lines = response.Trim().Split('\n');
+        foreach (var line in lines)
+        {
+            var fullLine = line.Trim();
+            if (fullLine.Length == 0) continue;
+
+            string lineNumberStr = "";
+            foreach (var ch in fullLine)
+            {
+                if (char.IsDigit(ch)) lineNumberStr += ch;
+                else break;
+            }
+
+            int lineNumber = 0;
+            if(!string.IsNullOrEmpty(lineNumberStr)) int.TryParse(lineNumberStr, out lineNumber);
+
+            lineComments.Add(new LineComment
+            {
+                Line = lineNumber,
+                Comment = fullLine
+            });
         }
+        return lineComments;
 
-        return string.Join("", content).Trim();
     }
 }
diff --git a/Services/GitHubService.cs b/Services/GitHubService.cs
index 94a7988..b5988bd 100644
--- a/Services/GitHubService.cs
+++ b/Services/GitHubService.cs
@@ -1,5 +1,6 @@
 ﻿using THESSA.Contract;
 using THESSA.Models;
+using THESSA.Helper;
 
 namespace THESSA.Services;
 
@@ -14,13 +15,69 @@ public GitHubService(IGitHub gitHubRepository, ILogger<GitHubService> logger)
         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
 
     }
-    public Task<string?> PostCommentToLineAsync(string token, PostCommentToLineRequestBody requestBody, RepositoryMetadata repoMetadata)
+    public async Task<bool> PostCommentToLineAsync(string token, string message, string commitId, string filePath, int position, RepositoryMetadata repoMetadata)
     {
-        throw new NotImplementedException();
+        try
+        {
+            var requestBody = new PostCommentToLineRequestBody
+            {
+                body = message,
+                commit_id = commitId,
+                path = filePath,
+                position = position
+
+            };
+
+            var response = await _gitHubRepository.PostCommentToLineAsync(token, requestBody, repoMetadata);
+            _logger.LogInformation($"Review Posted: {response}");
+            return true;
+
+        }
+        catch (Exception ex)
+        {
+            _logger.LogError(ex, "Error posting comment to line");
+            return false;
+        }
+    }
+
+    public async Task<List<FileData>> GetFilesDiffAsync(string token, RepositoryMetadata repoMetadata)
+    {
+        try
+        {
+            return await _gitHubRepository.GetDiffFilesAsync(token, repoMetadata);
+        }
+        catch (Exception ex)
+        {
+            _logger.LogError(ex, "Error getting files diff");
+            throw;
+        }
+    }
+
+    public async Task<string> GetFileContentAsync(string token, string fileUrl)
+    {
+        try
+        {
+            return await _gitHubRepository.GetFileContentAsync(token, fileUrl);
+        }
+        catch (Exception ex)
+        {
+            _logger.LogError(ex, "Error getting file content");
+            throw;
+        }
     }
 
-    public Task<string?> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData)
+    public async Task<bool> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData)
     {
-        throw new NotImplementedException();
+        try
+        {
+            var response = await _gitHubRepository.PostGeneralCommentAsync(text, token, repoMetaData);
+            _logger.LogInformation($"Posted General Review: {response}");
+            return true;
+        }
+        catch (Exception ex)
+        {
+            _logger.LogError(ex, "Error posting general comment");
+            throw;
+        }
     }
 }
diff --git a/Services/ThessaService.cs b/Services/ThessaService.cs
new file mode 100644
index 0000000..45c24ca
--- /dev/null
+++ b/Services/ThessaService.cs
@@ -0,0 +1,56 @@
+﻿using THESSA.Contract;
+using THESSA.Models;
+
+namespace THESSA.Services
+{
+    public class ThessaService : IThessaService
+    {
+        private readonly ILogger<ThessaService> _logger;
+        private readonly IThessaBotRepository _thessaRepos;
+        public ThessaService(
+            ILogger<ThessaService> logger,
+            IThessaBotRepository thessaRepos)
+        {
+            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _thessaRepos = thessaRepos ?? throw new ArgumentNullException(nameof(thessaRepos));
+        }
+        public bool IsNoIssueText(string source)
+        {
+            try
+            {
+                return _thessaRepos.IsNoIssueText(source);
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Error when checking if source is no issue.");
+                throw;
+            }
+        }
+
+        public async Task<string> ReviewAsync(string code, string diff)
+        {
+            try
+            {
+                return await _thessaRepos.RequestDiffs(code, diff);
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Error when requesting Thessa review.");
+                throw;
+            }
+        }
+
+        public List<LineComment> SplitReview(string response)
+        {
+            try
+            {
+                return _thessaRepos.SplitThessaReview(response);
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Error when splitting Thessa review response.");
+                throw;
+            }
+        }
+    }
+}
diff --git a/THESSA.csproj b/THESSA.csproj
index d1be524..b0ef4e5 100644
--- a/THESSA.csproj
+++ b/THESSA.csproj
@@ -14,10 +14,6 @@
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
   </ItemGroup>
 
-  <ItemGroup>
-    <Folder Include="Helper\" />
-  </ItemGroup>
-
   <ItemGroup>
     <None Include=".github\workflows\review.yml" />
   </ItemGroup>


Reviews:
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:34Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:35Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:36Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:37Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:38Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:39Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:40Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:44Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:45Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:46Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:57Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:58Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:15:59Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:16:00Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:16:01Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:16:02Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:16:03Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T04:16:04Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:08:36Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:08:37Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:08:38Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:08:39Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:08:40Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:08:40Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:08:41Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:08:42Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:08:43Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:08:44Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:08:45Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:35Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:36Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:37Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:37Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:38Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:39Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:40Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:41Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:42Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:43Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:44Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:25:45Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:29:49Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:29:50Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:29:51Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:29:52Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:29:53Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:29:54Z
user: login: JinoSejera
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-26T05:29:55Z

Review comments:
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 41: file.ContentUrl! - If ContentUrl is null, a NullReferenceException will be thrown due to the use of the null-forgiving operator (!).
created_at: 2025-05-26T04:15:34Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 44: file.Content! - If Content is null, a NullReferenceException will be thrown due to the use of the null-forgiving operator (!).
created_at: 2025-05-26T04:15:35Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 48: file.Patch! - If Patch is null, a NullReferenceException will be thrown due to the use of the null-forgiving operator (!).
created_at: 2025-05-26T04:15:36Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 65: lineComment.Comment! - If Comment is null, a NullReferenceException will be thrown due to the use of the null-forgiving operator (!).
created_at: 2025-05-26T04:15:37Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 66: file.CommitId! - If CommitId is null, a NullReferenceException will be thrown due to the use of the null-forgiving operator (!).
created_at: 2025-05-26T04:15:38Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 67: file.FileName! - If FileName is null, a NullReferenceException will be thrown due to the use of the null-forgiving operator (!).
created_at: 2025-05-26T04:15:39Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 69: lineComment.Comment! - If Comment is null, a NullReferenceException will be thrown due to the use of the null-forgiving operator (!).
created_at: 2025-05-26T04:15:40Z
author_association: OWNER
diff_hunk: @@ -0,0 +1,30 @@
+﻿using System.Text;
+
+namespace THESSA.Helper;
+
+public static class Utils
+{
+    public static string DecodeContentBase64(string content)
+    {
+        if (string.IsNullOrWhiteSpace(content)) 
+            throw new ArgumentNullException("Content cannot be null or Empty", nameof(content));
path: Helper/Utils.cs
user: login: JinoSejera
body: 10: The first argument to ArgumentNullException should be the parameter name, but the message is passed as the first argument and the parameter name as the second, which may cause confusion and incorrect exception information.
created_at: 2025-05-26T04:15:44Z
author_association: OWNER
diff_hunk: @@ -0,0 +1,30 @@
+﻿using System.Text;
+
+namespace THESSA.Helper;
+
+public static class Utils
+{
+    public static string DecodeContentBase64(string content)
+    {
+        if (string.IsNullOrWhiteSpace(content)) 
+            throw new ArgumentNullException("Content cannot be null or Empty", nameof(content));
path: Helper/Utils.cs
user: login: JinoSejera
body: 10: If content is whitespace, an ArgumentNullException is thrown, but the message "Content cannot be null or Empty" is passed as the first argument instead of the parameter name, which is not standard usage and may lead to misleading exception details.
created_at: 2025-05-26T04:15:45Z
author_association: OWNER
diff_hunk: @@ -0,0 +1,30 @@
+﻿using System.Text;
+
+namespace THESSA.Helper;
+
+public static class Utils
+{
+    public static string DecodeContentBase64(string content)
+    {
+        if (string.IsNullOrWhiteSpace(content)) 
+            throw new ArgumentNullException("Content cannot be null or Empty", nameof(content));
+
+        // Normalize by Removing escape characters and trimming whitespaces
+
+        var normalize = content
+            .Replace("\n", "")
+            .Replace("\r", "")
+            .Replace("\\n", "")
+            .Trim();
+
+        try
+        {
+            byte[] data = Convert.FromBase64String(normalize);
+            return Encoding.UTF8.GetString(data);
+        }
+        catch (Exception ex)
+        {
path: Helper/Utils.cs
user: login: JinoSejera
body: 26: Catching general Exception is not recommended; it may mask unexpected errors unrelated to Base64 decoding.
created_at: 2025-05-26T04:15:46Z
author_association: OWNER
diff_hunk: @@ -22,15 +23,82 @@ public GitHubRepository(HttpClient httpClient)
         {
             SetGitHubHeaders(token);
             string url = GetAddCommentURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
-            return await PostJsonAsync(url, requestBody, "line comment");
+            var response = await PostJsonAsync(url, requestBody, "line comment");
+
+            return await response.Content.ReadAsStringAsync();
         }
 
         public async Task<string?> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData)
         {
             SetGitHubHeaders(token);
             var body = new { body = text };
             string url = GetAddIssueURL(repoMetaData.RepositoryOwner!, repoMetaData.RepositoryName!, repoMetaData.PullRequestNumber);
-            return await PostJsonAsync(url, body, "general comment");
+            var response = await PostJsonAsync(url, body, "general comment");
+
+            return await response.Content.ReadAsStringAsync();
+        }
+
+        public async Task<List<FileData>> GetDiffFilesAsync(string token, RepositoryMetadata repoMetadata)
+        {
+            SetGitHubHeaders(token);
+            string url = GetFileListURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
+            var response = await GetJsonAsync(url);
+            var json = await response.Content.ReadAsStringAsync();
+
+            var result = new List<FileData>();
+            using (var doc = JsonDocument.Parse(json))
+            {
path: Repository/GitHubRepository.cs
user: login: JinoSejera
body: 38: If the JSON returned by the GitHub API is not a valid array, JsonDocument.Parse(json) or doc.RootElement.EnumerateArray() will throw an exception, causing an unhandled exception.
created_at: 2025-05-26T04:15:57Z
author_association: OWNER
diff_hunk: @@ -22,15 +23,82 @@ public GitHubRepository(HttpClient httpClient)
         {
             SetGitHubHeaders(token);
             string url = GetAddCommentURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
-            return await PostJsonAsync(url, requestBody, "line comment");
+            var response = await PostJsonAsync(url, requestBody, "line comment");
+
+            return await response.Content.ReadAsStringAsync();
         }
 
         public async Task<string?> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData)
         {
             SetGitHubHeaders(token);
             var body = new { body = text };
             string url = GetAddIssueURL(repoMetaData.RepositoryOwner!, repoMetaData.RepositoryName!, repoMetaData.PullRequestNumber);
-            return await PostJsonAsync(url, body, "general comment");
+            var response = await PostJsonAsync(url, body, "general comment");
+
+            return await response.Content.ReadAsStringAsync();
+        }
+
+        public async Task<List<FileData>> GetDiffFilesAsync(string token, RepositoryMetadata repoMetadata)
+        {
+            SetGitHubHeaders(token);
+            string url = GetFileListURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
+            var response = await GetJsonAsync(url);
+            var json = await response.Content.ReadAsStringAsync();
+
+            var result = new List<FileData>();
+            using (var doc = JsonDocument.Parse(json))
+            {
+                foreach (var element in doc.RootElement.EnumerateArray())
+                {
+                    if (element.TryGetProperty("contents_url", out var contentsUrlProp) && element.TryGetProperty("filename", out var filenameProp) && element.TryGetProperty("patch", out var patchProp))
path: Repository/GitHubRepository.cs
user: login: JinoSejera
body: 41: If any of the expected properties ("contents_url", "filename", "patch") are missing in an element, that file will be skipped without notification; if all are missing, result may be empty.
created_at: 2025-05-26T04:15:58Z
author_association: OWNER
diff_hunk: @@ -22,15 +23,82 @@ public GitHubRepository(HttpClient httpClient)
         {
             SetGitHubHeaders(token);
             string url = GetAddCommentURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
-            return await PostJsonAsync(url, requestBody, "line comment");
+            var response = await PostJsonAsync(url, requestBody, "line comment");
+
+            return await response.Content.ReadAsStringAsync();
         }
 
         public async Task<string?> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData)
         {
             SetGitHubHeaders(token);
             var body = new { body = text };
             string url = GetAddIssueURL(repoMetaData.RepositoryOwner!, repoMetaData.RepositoryName!, repoMetaData.PullRequestNumber);
-            return await PostJsonAsync(url, body, "general comment");
+            var response = await PostJsonAsync(url, body, "general comment");
+
+            return await response.Content.ReadAsStringAsync();
+        }
+
+        public async Task<List<FileData>> GetDiffFilesAsync(string token, RepositoryMetadata repoMetadata)
+        {
+            SetGitHubHeaders(token);
+            string url = GetFileListURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
+            var response = await GetJsonAsync(url);
+            var json = await response.Content.ReadAsStringAsync();
+
+            var result = new List<FileData>();
+            using (var doc = JsonDocument.Parse(json))
+            {
+                foreach (var element in doc.RootElement.EnumerateArray())
+                {
+                    if (element.TryGetProperty("contents_url", out var contentsUrlProp) && element.TryGetProperty("filename", out var filenameProp) && element.TryGetProperty("patch", out var patchProp))
+                    {
+                        var fileData = new FileData();
+                        var contentsUrl = contentsUrlProp.GetString();
+                        var filename = filenameProp.GetString();
+                        var patch = patchProp.GetString();
+                        if (!string.IsNullOrEmpty(contentsUrl))
+                        {
path: Repository/GitHubRepository.cs
user: login: JinoSejera
body: 48: If contentsUrl is not a valid URI, new Uri(contentsUrl) will throw a UriFormatException, causing an unhandled exception.
created_at: 2025-05-26T04:15:59Z
author_association: OWNER
diff_hunk: @@ -22,15 +23,82 @@ public GitHubRepository(HttpClient httpClient)
         {
             SetGitHubHeaders(token);
             string url = GetAddCommentURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
-            return await PostJsonAsync(url, requestBody, "line comment");
+            var response = await PostJsonAsync(url, requestBody, "line comment");
+
+            return await response.Content.ReadAsStringAsync();
         }
 
         public async Task<string?> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData)
         {
             SetGitHubHeaders(token);
             var body = new { body = text };
             string url = GetAddIssueURL(repoMetaData.RepositoryOwner!, repoMetaData.RepositoryName!, repoMetaData.PullRequestNumber);
-            return await PostJsonAsync(url, body, "general comment");
+            var response = await PostJsonAsync(url, body, "general comment");
+
+            return await response.Content.ReadAsStringAsync();
+        }
+
+        public async Task<List<FileData>> GetDiffFilesAsync(string token, RepositoryMetadata repoMetadata)
+        {
+            SetGitHubHeaders(token);
+            string url = GetFileListURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
+            var response = await GetJsonAsync(url);
+            var json = await response.Content.ReadAsStringAsync();
+
+            var result = new List<FileData>();
+            using (var doc = JsonDocument.Parse(json))
+            {
+                foreach (var element in doc.RootElement.EnumerateArray())
+                {
+                    if (element.TryGetProperty("contents_url", out var contentsUrlProp) && element.TryGetProperty("filename", out var filenameProp) && element.TryGetProperty("patch", out var patchProp))
+                    {
+                        var fileData = new FileData();
+                        var contentsUrl = contentsUrlProp.GetString();
+                        var filename = filenameProp.GetString();
+                        var patch = patchProp.GetString();
+                        if (!string.IsNullOrEmpty(contentsUrl))
+                        {
+                            fileData.ContentUrl = contentsUrl;
+
+                            Uri contentUri = new Uri(contentsUrl);
path: Repository/GitHubRepository.cs
user: login: JinoSejera
body: 51: If the query string does not contain a "ref" parameter, fileData.CommitId will be set to null, which may cause issues if not handled elsewhere.
created_at: 2025-05-26T04:16:00Z
author_association: OWNER
diff_hunk: @@ -22,15 +23,82 @@ public GitHubRepository(HttpClient httpClient)
         {
             SetGitHubHeaders(token);
             string url = GetAddCommentURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
-            return await PostJsonAsync(url, requestBody, "line comment");
+            var response = await PostJsonAsync(url, requestBody, "line comment");
+
+            return await response.Content.ReadAsStringAsync();
         }
 
         public async Task<string?> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData)
         {
             SetGitHubHeaders(token);
             var body = new { body = text };
             string url = GetAddIssueURL(repoMetaData.RepositoryOwner!, repoMetaData.RepositoryName!, repoMetaData.PullRequestNumber);
-            return await PostJsonAsync(url, body, "general comment");
+            var response = await PostJsonAsync(url, body, "general comment");
+
+            return await response.Content.ReadAsStringAsync();
+        }
+
+        public async Task<List<FileData>> GetDiffFilesAsync(string token, RepositoryMetadata repoMetadata)
+        {
+            SetGitHubHeaders(token);
+            string url = GetFileListURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
+            var response = await GetJsonAsync(url);
+            var json = await response.Content.ReadAsStringAsync();
+
+            var result = new List<FileData>();
+            using (var doc = JsonDocument.Parse(json))
+            {
+                foreach (var element in doc.RootElement.EnumerateArray())
+                {
+                    if (element.TryGetProperty("contents_url", out var contentsUrlProp) && element.TryGetProperty("filename", out var filenameProp) && element.TryGetProperty("patch", out var patchProp))
+                    {
+                        var fileData = new FileData();
+                        var contentsUrl = contentsUrlProp.GetString();
+                        var filename = filenameProp.GetString();
+                        var patch = patchProp.GetString();
+                        if (!string.IsNullOrEmpty(contentsUrl))
+                        {
+                            fileData.ContentUrl = contentsUrl;
+
+                            Uri contentUri = new Uri(contentsUrl);
+                            string query = contentUri.Query;
+
+                            var queryParams = HttpUtility.ParseQueryString(query);
+                            fileData.CommitId = queryParams["ref"];
+                        }
+                        if (!string.IsNullOrEmpty(filename))
+                        {
+                            fileData.FileName = filename;
+                        }
+                        if (!string.IsNullOrEmpty(patch))
+                        {
+                            fileData.Patch = patch;
+                        }
+                        result.Add(fileData);
+                    }
+                }
+            }
+            return result;
path: Repository/GitHubRepository.cs
user: login: JinoSejera
body: 69: If the JSON returned by the GitHub API is not a valid object, or is missing the "content" property, JsonDocument.Parse(json) or doc.RootElement.TryGetProperty will fail, causing an unhandled exception or a RepositoryException.
created_at: 2025-05-26T04:16:01Z
author_association: OWNER
diff_hunk: @@ -22,15 +23,82 @@ public GitHubRepository(HttpClient httpClient)
         {
             SetGitHubHeaders(token);
             string url = GetAddCommentURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
-            return await PostJsonAsync(url, requestBody, "line comment");
+            var response = await PostJsonAsync(url, requestBody, "line comment");
+
+            return await response.Content.ReadAsStringAsync();
         }
 
         public async Task<string?> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData)
         {
             SetGitHubHeaders(token);
             var body = new { body = text };
             string url = GetAddIssueURL(repoMetaData.RepositoryOwner!, repoMetaData.RepositoryName!, repoMetaData.PullRequestNumber);
-            return await PostJsonAsync(url, body, "general comment");
+            var response = await PostJsonAsync(url, body, "general comment");
+
+            return await response.Content.ReadAsStringAsync();
+        }
+
+        public async Task<List<FileData>> GetDiffFilesAsync(string token, RepositoryMetadata repoMetadata)
+        {
+            SetGitHubHeaders(token);
+            string url = GetFileListURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
+            var response = await GetJsonAsync(url);
+            var json = await response.Content.ReadAsStringAsync();
+
+            var result = new List<FileData>();
+            using (var doc = JsonDocument.Parse(json))
+            {
+                foreach (var element in doc.RootElement.EnumerateArray())
+                {
+                    if (element.TryGetProperty("contents_url", out var contentsUrlProp) && element.TryGetProperty("filename", out var filenameProp) && element.TryGetProperty("patch", out var patchProp))
+                    {
+                        var fileData = new FileData();
+                        var contentsUrl = contentsUrlProp.GetString();
+                        var filename = filenameProp.GetString();
+                        var patch = patchProp.GetString();
+                        if (!string.IsNullOrEmpty(contentsUrl))
+                        {
+                            fileData.ContentUrl = contentsUrl;
+
+                            Uri contentUri = new Uri(contentsUrl);
+                            string query = contentUri.Query;
+
+                            var queryParams = HttpUtility.ParseQueryString(query);
+                            fileData.CommitId = queryParams["ref"];
+                        }
+                        if (!string.IsNullOrEmpty(filename))
+                        {
+                            fileData.FileName = filename;
+                        }
+                        if (!string.IsNullOrEmpty(patch))
+                        {
+                            fileData.Patch = patch;
+                        }
+                        result.Add(fileData);
+                    }
+                }
+            }
+            return result;
+        }
+
path: Repository/GitHubRepository.cs
user: login: JinoSejera
body: 71: contentProp.GetString()! uses the null-forgiving operator; if "content" is null, a NullReferenceException will be thrown.
created_at: 2025-05-26T04:16:02Z
author_association: OWNER
diff_hunk: @@ -22,15 +23,82 @@ public GitHubRepository(HttpClient httpClient)
         {
             SetGitHubHeaders(token);
             string url = GetAddCommentURL(repoMetadata.RepositoryOwner!, repoMetadata.RepositoryName!, repoMetadata.PullRequestNumber);
-            return await PostJsonAsync(url, requestBody, "line comment");
+            var response = await PostJsonAsync(url, requestBody, "line comment");
+
+            return await response.Content.ReadAsStringAsync();
         }
 
         public async Task<string?> PostGeneralCommentAsync(string text, string token, RepositoryMetadata repoMetaData)
         {
             SetGitHubHeaders(token);
             var body = new { body = text };
             string url = GetAddIssueURL(repoMetaData.RepositoryOwner!, repoMetaData.RepositoryName!, repoMetaData.PullRequestNumber);
path: Repository/GitHubRepository.cs
user: login: JinoSejera
body: 22, 29: If the response from PostJsonAsync is not a valid JSON or does not contain expected fields, ReadAsStringAsync may return unexpected results, but this is not directly handled.
created_at: 2025-05-26T04:16:03Z
author_association: OWNER
diff_hunk: @@ -3,6 +3,7 @@
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
+using System.Web;
 using THESSA.Contract;
 using THESSA.Models;
path: Repository/GitHubRepository.cs
user: login: JinoSejera
body: 6: System.Web is not available in .NET Core/.NET 5+ by default; using HttpUtility may cause a runtime error if the correct package is not referenced.
created_at: 2025-05-26T04:16:04Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 46: file.ContentUrl is accessed with ! (null-forgiving), but if it is actually null, GetFileContentAsync may throw an exception.
created_at: 2025-05-26T05:08:36Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 47: Utils.DecodeContentBase64(content) assumes content is not null; if GetFileContentAsync returns null, this may throw.
created_at: 2025-05-26T05:08:37Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 52: Path.GetExtension(file.FileName) assumes file.FileName is not null; if it is null, this will throw an ArgumentNullException.
created_at: 2025-05-26T05:08:38Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 55: file.Content!.Length is accessed with ! (null-forgiving), but if file.Content is null, this will throw a NullReferenceException.
created_at: 2025-05-26T05:08:39Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 60: file.Patch!.Length is accessed with ! (null-forgiving), but if file.Patch is null, this will throw a NullReferenceException.
created_at: 2025-05-26T05:08:39Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 67: _thessaService.ReviewAsync(file.Content, file.Patch) passes file.Content and file.Patch, which may be null if previous checks are bypassed.
created_at: 2025-05-26T05:08:40Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 74: lineComment.Comment! is used with null-forgiving operator, but if Comment is null, this will throw in PostCommentToLineAsync or PostGeneralCommentAsync.
created_at: 2025-05-26T05:08:41Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 75: file.CommitId! and file.FileName! are used with null-forgiving operator, but if either is null, this will throw in PostCommentToLineAsync.
created_at: 2025-05-26T05:08:42Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 75: lineComment.Line is checked for null, but if it is null, the else branch will not post a line comment, possibly missing intended comments.
created_at: 2025-05-26T05:08:43Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
+
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 76: reviewResult is overwritten in each iteration, so only the last comment's result is preserved, which may not reflect the overall review status.
created_at: 2025-05-26T05:08:44Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
+
+                await Task.WhenAll(contentTasks);
+
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 78: lineComment.Comment! is used again with null-forgiving operator, but if Comment is null, this will throw in PostGeneralCommentAsync.
created_at: 2025-05-26T05:08:45Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 54: file.ContentUrl is accessed with ! (null-forgiving), but if ContentUrl is null, GetFileContentAsync will throw a NullReferenceException.
created_at: 2025-05-26T05:25:35Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 61: file.Content is set from DecodeContentBase64, but if content is null or invalid base64, DecodeContentBase64 may throw an exception.
created_at: 2025-05-26T05:25:35Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 68: Path.GetExtension(file.FileName) is called without checking if file.FileName is null, which could throw an ArgumentNullException.
created_at: 2025-05-26T05:25:36Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 72: file.Content! is accessed with !, but if file.Content is null, accessing Length will throw a NullReferenceException.
created_at: 2025-05-26T05:25:37Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
+
+                await Task.WhenAll(contentTasks);
+
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 78: file.Patch! is accessed with !, but if file.Patch is null, accessing Length will throw a NullReferenceException.
created_at: 2025-05-26T05:25:38Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
+
+                await Task.WhenAll(contentTasks);
+
+                foreach (var file in changedFiles)
+                {
+                    // Checking if file extension of file to review is supported
+                    var fileExtension = Path.GetExtension(file.FileName);
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 82: _thessaService.ReviewAsync(file.Content, file.Patch) is called without checking if file.Content or file.Patch are null, which could cause exceptions in the implementation.
created_at: 2025-05-26T05:25:39Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
+
+                await Task.WhenAll(contentTasks);
+
+                foreach (var file in changedFiles)
+                {
+                    // Checking if file extension of file to review is supported
+                    var fileExtension = Path.GetExtension(file.FileName);
+                    if (!extensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase))
+                    {
+                        _logger.LogWarning($"Skipping, unsupported extension: {fileExtension} file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Checking if File content is empty
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 89: _thessaService.IsNoIssueText(thessaReview) is called without checking if thessaReview is null, which could cause a NullReferenceException.
created_at: 2025-05-26T05:25:40Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
+
+                await Task.WhenAll(contentTasks);
+
+                foreach (var file in changedFiles)
+                {
+                    // Checking if file extension of file to review is supported
+                    var fileExtension = Path.GetExtension(file.FileName);
+                    if (!extensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase))
+                    {
+                        _logger.LogWarning($"Skipping, unsupported extension: {fileExtension} file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Checking if File content is empty
+                    if (file.Content!.Length == 0)
+                    {
+                        _logger.LogWarning($"Skipping, empty content for file: {file.FileName}");
+                        continue;
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 93: _thessaService.SplitReview(thessaReview) is called without checking if thessaReview is null, which could cause a NullReferenceException.
created_at: 2025-05-26T05:25:41Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
+
+                await Task.WhenAll(contentTasks);
+
+                foreach (var file in changedFiles)
+                {
+                    // Checking if file extension of file to review is supported
+                    var fileExtension = Path.GetExtension(file.FileName);
+                    if (!extensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase))
+                    {
+                        _logger.LogWarning($"Skipping, unsupported extension: {fileExtension} file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Checking if File content is empty
+                    if (file.Content!.Length == 0)
+                    {
+                        _logger.LogWarning($"Skipping, empty content for file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Check if File Diff is Empty
+                    if (file.Patch!.Length == 0)
+                        _logger.LogWarning($"diff for file: {file.FileName} is Empty");
+
+                    string separator = "\n\n----------------------------------------------------------------------\n\n";
+                    _logger.LogInformation($"Asking Review for THESSA AI... Content Length: {file.Content.Length} Diff Length: {file.Patch.Length}.");
+
+                    var thessaReview = await _thessaService.ReviewAsync(file.Content, file.Patch);
+
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 104: lineComment.Comment! is used without checking if Comment is null, which could cause a NullReferenceException.
created_at: 2025-05-26T05:25:42Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
+
+                await Task.WhenAll(contentTasks);
+
+                foreach (var file in changedFiles)
+                {
+                    // Checking if file extension of file to review is supported
+                    var fileExtension = Path.GetExtension(file.FileName);
+                    if (!extensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase))
+                    {
+                        _logger.LogWarning($"Skipping, unsupported extension: {fileExtension} file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Checking if File content is empty
+                    if (file.Content!.Length == 0)
+                    {
+                        _logger.LogWarning($"Skipping, empty content for file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Check if File Diff is Empty
+                    if (file.Patch!.Length == 0)
+                        _logger.LogWarning($"diff for file: {file.FileName} is Empty");
+
+                    string separator = "\n\n----------------------------------------------------------------------\n\n";
+                    _logger.LogInformation($"Asking Review for THESSA AI... Content Length: {file.Content.Length} Diff Length: {file.Patch.Length}.");
+
+                    var thessaReview = await _thessaService.ReviewAsync(file.Content, file.Patch);
+
+                    _logger.LogInformation($"{separator}{file.Content}{separator}{file.Patch}{separator}{thessaReview}{separator}");
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 105: file.CommitId! is used without checking if CommitId is null, which could cause a NullReferenceException.
created_at: 2025-05-26T05:25:43Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
+
+                await Task.WhenAll(contentTasks);
+
+                foreach (var file in changedFiles)
+                {
+                    // Checking if file extension of file to review is supported
+                    var fileExtension = Path.GetExtension(file.FileName);
+                    if (!extensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase))
+                    {
+                        _logger.LogWarning($"Skipping, unsupported extension: {fileExtension} file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Checking if File content is empty
+                    if (file.Content!.Length == 0)
+                    {
+                        _logger.LogWarning($"Skipping, empty content for file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Check if File Diff is Empty
+                    if (file.Patch!.Length == 0)
+                        _logger.LogWarning($"diff for file: {file.FileName} is Empty");
+
+                    string separator = "\n\n----------------------------------------------------------------------\n\n";
+                    _logger.LogInformation($"Asking Review for THESSA AI... Content Length: {file.Content.Length} Diff Length: {file.Patch.Length}.");
+
+                    var thessaReview = await _thessaService.ReviewAsync(file.Content, file.Patch);
+
+                    _logger.LogInformation($"{separator}{file.Content}{separator}{file.Patch}{separator}{thessaReview}{separator}");
+
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 106: file.FileName! is used without checking if FileName is null, which could cause a NullReferenceException.
created_at: 2025-05-26T05:25:44Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
+                {
+                    var content = await _gitHubService.GetFileContentAsync(metadata.Token, file.ContentUrl!);
+                    var decodedContent = Utils.DecodeContentBase64(content);
+                    file.Content = decodedContent;
+                }).ToList();
+
+                await Task.WhenAll(contentTasks);
+
+                foreach (var file in changedFiles)
+                {
+                    // Checking if file extension of file to review is supported
+                    var fileExtension = Path.GetExtension(file.FileName);
+                    if (!extensions.Contains(fileExtension, StringComparer.OrdinalIgnoreCase))
+                    {
+                        _logger.LogWarning($"Skipping, unsupported extension: {fileExtension} file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Checking if File content is empty
+                    if (file.Content!.Length == 0)
+                    {
+                        _logger.LogWarning($"Skipping, empty content for file: {file.FileName}");
+                        continue;
+                    }
+
+                    // Check if File Diff is Empty
+                    if (file.Patch!.Length == 0)
+                        _logger.LogWarning($"diff for file: {file.FileName} is Empty");
+
+                    string separator = "\n\n----------------------------------------------------------------------\n\n";
+                    _logger.LogInformation($"Asking Review for THESSA AI... Content Length: {file.Content.Length} Diff Length: {file.Patch.Length}.");
+
+                    var thessaReview = await _thessaService.ReviewAsync(file.Content, file.Patch);
+
+                    _logger.LogInformation($"{separator}{file.Content}{separator}{file.Patch}{separator}{thessaReview}{separator}");
+
+                    if (_thessaService.IsNoIssueText(thessaReview))
+                        _logger.LogInformation($"File: {file.FileName} looks good. Continue.");
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 108: lineComment.Comment! is used without checking if Comment is null, which could cause a NullReferenceException.
created_at: 2025-05-26T05:25:45Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 41: file.ContentUrl is accessed with ! (null-forgiving), but if ContentUrl is null, GetFileContentAsync will throw a NullReferenceException.
created_at: 2025-05-26T05:29:49Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 49: file.Content is accessed with ! (null-forgiving), but if Utils.DecodeContentBase64 returns null, file.Content!.Length will throw a NullReferenceException.
created_at: 2025-05-26T05:29:50Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 54: file.Patch is accessed with ! (null-forgiving), but if file.Patch is null, file.Patch!.Length will throw a NullReferenceException.
created_at: 2025-05-26T05:29:51Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 62: lineComment.Comment is accessed with ! (null-forgiving), but if lineComment.Comment is null, PostCommentToLineAsync will throw a NullReferenceException.
created_at: 2025-05-26T05:29:52Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 63: file.CommitId is accessed with ! (null-forgiving), but if file.CommitId is null, PostCommentToLineAsync will throw a NullReferenceException.
created_at: 2025-05-26T05:29:53Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 64: file.FileName is accessed with ! (null-forgiving), but if file.FileName is null, PostCommentToLineAsync will throw a NullReferenceException.
created_at: 2025-05-26T05:29:54Z
author_association: OWNER
diff_hunk: @@ -13,25 +17,131 @@ namespace THESSA.Controllers
     public class GitHubController : ControllerBase
     {
         private readonly ILogger<GitHubController> _logger;
-        public GitHubController(ILogger<GitHubController> logger)
+        private readonly IGithubService _gitHubService;
+        private readonly IThessaService _thessaService;
+        public GitHubController(
+            ILogger<GitHubController> logger,
+            IGithubService gitHubService,
+            IThessaService thessaService
+            )
         {
             _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+            _gitHubService = gitHubService ?? throw new ArgumentNullException(nameof(gitHubService));
+            _thessaService = thessaService ?? throw new ArgumentNullException(nameof(thessaService));
 
         }
         [HttpPost]
-        public IActionResult PostReview(
+        public async Task<IActionResult> PostReview(
             [FromHeader] GitHubMetadata metadata,
             [FromBody] GitHubRequestBody body)
         {
             if (metadata == null || body == null)
             {
                 return BadRequest("Metadata and body cannot be null");
             }
-            _logger.LogInformation(metadata.ToString());
-            _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
-            // Process the data here
-            // For example, you can log it or perform some action
-            return Ok("Data received successfully");
+            try
+            {
+                string[] extensions;
+                if (!string.IsNullOrEmpty(metadata.TargetExtensions))
+                    extensions = metadata.TargetExtensions
+                        .Split(',', StringSplitOptions.RemoveEmptyEntries)
+                        .Select(ext => ext.Trim())
+                        .ToArray();
+                else extensions = [".cs", ".py"]; // Default file extensions
+
+                _logger.LogInformation($"Received GitHub request with metadata: {JsonSerializer.Serialize(metadata)} and body: {JsonSerializer.Serialize(body)}");
+                // Process the data here
+                // For example, you can log it or perform some action
+
+                var repositoryRequestMetaData = new RepositoryMetadata
+                {
+                    RepositoryOwner = body.RepositoryOwner,
+                    RepositoryName = body.RepositoryName,
+                    PullRequestNumber = body.PullRequestNumber
+                };
+
+                var changedFiles = await _gitHubService.GetFilesDiffAsync(metadata.Token, repositoryRequestMetaData);
+
+                // Replace the foreach loop with parallel async processing
+                var contentTasks = changedFiles.Select(async file =>
path: Controllers/GitHubController.cs
user: login: JinoSejera
body: 66: lineComment.Comment is accessed with ! (null-forgiving), but if lineComment.Comment is null, PostGeneralCommentAsync will throw a NullReferenceException.
created_at: 2025-05-26T05:29:55Z
author_association: OWNER

PR comments:
user: login: JinoSejera
created_at: 2025-05-26T04:15:41Z
body: Additionally, if any of the awaited service methods (_gitHubService.GetFilesDiffAsync, _gitHubService.GetFileContentAsync, _thessaService.ReviewAsync, _gitHubService.PostCommentToLineAsync, _gitHubService.PostGeneralCommentAsync) throw exceptions not handled internally, they will be caught by the outer try-catch and result in a 500 response, but the specific file or line causing the issue may not be clear to the client.
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T04:15:48Z
body: No critical crashes or unhandled exceptions, but exception handling and ArgumentNullException usage are not standard.
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T04:15:52Z
body: 14: CommitId can be null despite [Required] attribute, which may cause validation to pass incorrectly or lead to null reference exceptions if CommitId is accessed without null checks.
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:08:26Z
body: 3: use of HTML entity &lt; in List&lt;string&gt; instead of generic syntax List<string> causes a compilation error
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:08:27Z
body: No other critical issues found.
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:08:50Z
body: 19: possible ArgumentNullException if githubToken is null
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:08:51Z
body: 28: possible HttpRequestException or AggregateException if the HTTP request fails
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:08:52Z
body: 29: possible HttpRequestException if response is not successful
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:08:53Z
body: 30: possible AggregateException if reading content fails
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:08:55Z
body: 31: possible JsonException if response is not valid JSON
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:08:56Z
body: 32: possible IndexOutOfRangeException if the commits array is empty
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:08:57Z
body: 32: possible KeyNotFoundException or InvalidOperationException if "sha" property is missing
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:08:58Z
body: 32: possible NullReferenceException if GetString() returns null and null-forgiving operator is used
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:09:00Z
body: 37: possible HttpRequestException or AggregateException if the HTTP request fails
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:09:01Z
body: 38: possible HttpRequestException if response is not successful
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:09:02Z
body: 39: possible AggregateException if reading content fails
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:09:03Z
body: 40: possible JsonException if response is not valid JSON
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:09:05Z
body: 41: possible KeyNotFoundException if "files" property is missing
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:09:06Z
body: 44: possible KeyNotFoundException if "filename" property is missing
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:09:08Z
body: 44: possible NullReferenceException if GetString() returns null and null-forgiving operator is used
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:09:09Z
body: 50: possible HttpRequestException or AggregateException if the HTTP request fails
author_association: OWNER
user: login: JinoSejera
created_at: 2025-05-26T05:09:10Z
body: 51: possible HttpRequestException if response is not successful
author_association: OWNER