using ChatMvc.Models; using Microsoft.AspNetCore.Mvc; using System.Net.Http.Headers; using System.Net.Http; using System.Text; using System.Text.Json; using Newtonsoft.Json; using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Authorization; using System.Linq; using Microsoft.AspNetCore.Authentication; using Chat.Domain.Tools; using Newtonsoft.Json.Linq; namespace ChatMvc.Controllers { [Authorize] public class ChatController : Controller { private readonly IHttpClientFactory _httpClientFactory; private readonly IConfiguration _configuration; private readonly IAntiforgery _antiforgery; public ChatController(IHttpClientFactory httpClientFactory, IConfiguration configuration, IAntiforgery antiforgery) { _httpClientFactory = httpClientFactory; _configuration = configuration; _antiforgery = antiforgery; } public IActionResult Index() { var tokens = _antiforgery.GetAndStoreTokens(HttpContext); var token = HttpContext.GetTokenAsync("access_token").Result; ViewBag.Token = token; return View(); } [HttpPost("chat/proxy-response")] [ValidateAntiForgeryToken] public async Task ProxyResponse([FromForm] string sessionId, [FromForm] string message, [FromForm] IFormFile file1 = null, [FromForm] IFormFile file2 = null) { try { if (!Request.Headers["X-Requested-With"].Equals("XMLHttpRequest")) { return BadRequest("Requisição inválida"); } var userId = User.Claims.FirstOrDefault(f => f.Type == "UserId")?.Value; var name = User.Claims.FirstOrDefault(f => f.Type == "FirstName")?.Value; var company = User.Claims.FirstOrDefault(f => f.Type == "CompanyName")?.Value; var token = User.Claims.FirstOrDefault(f => f.Type == "TokenExternal")?.Value; if (string.IsNullOrEmpty(token)) { return BadRequest("Token não encontrado"); } // Verificar se há arquivos e palavras-chave var keyWords = new[] { "diferença", "diferenças", "comparação", "comparar", "compare" }; bool hasKeyword = keyWords.Any(k => message.ToLower().Contains(k.ToLower())); bool hasBothFiles = file1 != null && file2 != null; bool hasOneFile = file1 != null || file2 != null; bool isPDF = file1 != null && file1.ContentType == "application/pdf" && file2 != null && file2.ContentType == "application/pdf"; bool isImage = file1 != null && file1.ContentType.Contains("image") && file2 != null && file2.ContentType.Contains("image"); // Se tem apenas um arquivo ou se tem arquivos mas não tem palavra-chave if ((hasOneFile && !hasBothFiles) || (hasBothFiles && !hasKeyword)) { return Ok("Por favor, especifique o que deseja fazer com os arquivos. " + "Para comparar dois PDFs, inclua palavras como 'diferença' ou 'comparação' em sua mensagem."); } var client = _httpClientFactory.CreateClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Replace("Bearer ", "")); var baseUrl = _configuration["ExternalApiBaseUrl"]; if (hasBothFiles && hasKeyword && isPDF) { var content = await CompareFiles(baseUrl, sessionId, client, file1, file2); return Ok(content); } else if (hasBothFiles && hasKeyword && isImage) { var content = await CompareFilesImage(baseUrl, sessionId, client, file1, file2); return Ok(content); } var chatContent = new FormUrlEncodedContent(new[] { new KeyValuePair("sessionId", sessionId), new KeyValuePair("message", message) }); var response = await client.PostAsync($"{baseUrl}/chat/response", chatContent); response.EnsureSuccessStatusCode(); var responseContent = await response.Content.ReadAsStringAsync(); return Ok(responseContent); } catch (Exception ex) { return BadRequest($"Erro ao processar mensagem: {ex.Message}"); } } private async Task CompareFiles(string? baseUrl, string sessionId, HttpClient? client, [FromForm] IFormFile? file1 = null, [FromForm] IFormFile? file2 = null) { // Primeiro, comparar os PDFs var formData = new MultipartFormDataContent(); var content1 = new StreamContent(file1.OpenReadStream()); var content2 = new StreamContent(file2.OpenReadStream()); content1.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); content2.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); formData.Add(content1, "File1", file1.FileName); formData.Add(content2, "File2", file2.FileName); var comparisonResponse = await client.PostAsync( "https://localhost:7200/api/PdfComparison/compare", formData ); if (!comparisonResponse.IsSuccessStatusCode) { throw new Exception("Erro ao comparar os PDFs"); } var differences = await comparisonResponse.Content.ReadAsStringAsync(); var dynamicContent = JsonConvert.DeserializeObject(differences); var formattedDifferences = FormatDifferencesForChat(dynamicContent); var promptMessage = $"Ao comparar dois textos obtive as diferenças do json. Você poderia explicar e resumir: {formattedDifferences}"; var chatContentSend = new FormUrlEncodedContent(new[] { new KeyValuePair("sessionId", sessionId), new KeyValuePair("message", promptMessage) }); var chatResponse = await client.PostAsync($"{baseUrl}/chat/response-fromia", chatContentSend); chatResponse.EnsureSuccessStatusCode(); var content = await chatResponse.Content.ReadAsStringAsync(); return content; } private async Task CompareFilesImage(string? baseUrl, string sessionId, HttpClient? client, [FromForm] IFormFile? file1 = null, [FromForm] IFormFile? file2 = null) { var formData = new MultipartFormDataContent(); var content1 = new StreamContent(file1.OpenReadStream()); var content2 = new StreamContent(file2.OpenReadStream()); content1.Headers.ContentType = new MediaTypeHeaderValue(file1.ContentType); content2.Headers.ContentType = new MediaTypeHeaderValue(file2.ContentType); formData.Add(content1, "Drawing1", file1.FileName); formData.Add(content2, "Drawing2", file2.FileName); var comparisonResponse = await client.PostAsync( "https://localhost:7200/api/TechnicalDrawing/compare-images", formData ); if (!comparisonResponse.IsSuccessStatusCode) { throw new Exception("Erro ao comparar os PDFs"); } var differences = await comparisonResponse.Content.ReadAsStringAsync(); JObject obj = JObject.Parse(differences); string image = obj["image"].ToString(); var file3 = Base64ToFormFile.ConvertBase64ToFormFile(image, "compared.png"); var promptMessage = $"Ao comparar dois desenhos técnicos, obtive as diferenças entre eles. Você precisa explicar e resumir estas diferenças ressaltando mudanças em medidas da peça. O arquivo "; var response = ""; using (formData = AddFormDataToResponse(sessionId, promptMessage, file1, file2, file3)) { var chatResponse = await client.PostAsync($"{baseUrl}/chat/response-fromia", formData); chatResponse.EnsureSuccessStatusCode(); response = await chatResponse.Content.ReadAsStringAsync(); } return response; } private MultipartFormDataContent AddFormDataToResponse(string sessionId, string message, IFormFile? file1 = null, IFormFile? file2 = null, IFormFile? file3 = null) { var formData = new MultipartFormDataContent(); formData.Add(new StringContent(sessionId), "SessionId"); formData.Add(new StringContent(message), "Message"); if (file1 != null) { var streamContent1 = new StreamContent(file1.OpenReadStream()); formData.Add(streamContent1, "File1", file1.FileName); } if (file2 != null) { var streamContent2 = new StreamContent(file2.OpenReadStream()); formData.Add(streamContent2, "File2", file2.FileName); } if (file3 != null) { var streamContent3 = new StreamContent(file3.OpenReadStream()); formData.Add(streamContent3, "File3", file3.FileName); } return formData; } [HttpPost("chat/authenticate")] [ValidateAntiForgeryToken] public async Task Authenticate([FromBody] AuthenticateRequest request) { try { if (!Request.Headers["X-Requested-With"].Equals("XMLHttpRequest")) { return BadRequest("Requisição inválida"); } var client = _httpClientFactory.CreateClient(); var baseUrl = _configuration["ExternalApiBaseUrl"]; // Primeira requisição - newclient var newClientRequest = new { localId = request.UserId, companyTenant = request.Company, name = request.Name }; var newClientResponse = await client.PostAsync( $"{baseUrl}/login/newclient", new StringContent(JsonConvert.SerializeObject(newClientRequest), Encoding.UTF8, "application/json")); newClientResponse.EnsureSuccessStatusCode(); var clientContent = await newClientResponse.Content.ReadAsStringAsync(); var clientResult = JsonConvert.DeserializeObject(clientContent); // Segunda requisição - token var tokenRequest = new { clientId = request.UserId, clientName = request.Name, clientSecret = clientResult.Secret }; var tokenResponse = await client.PostAsync( $"{baseUrl}/login/token", new StringContent(JsonConvert.SerializeObject(tokenRequest), Encoding.UTF8, "application/json")); tokenResponse.EnsureSuccessStatusCode(); var tokenContent = await tokenResponse.Content.ReadAsStringAsync(); var tokenResult = JsonConvert.DeserializeObject(tokenContent); return Ok(new { token = tokenResult.Token }); } catch (Exception ex) { return BadRequest($"Erro na autenticação: {ex.Message}"); } } private string FormatDifferencesForChat(dynamic jsonDifferences) { var sb = new StringBuilder(); sb.AppendLine("Análise das diferenças entre os documentos:"); sb.AppendLine(); try { // Focar apenas nas diferenças reais (onlyDifferences) var onlyDiffs = jsonDifferences.onlyDifferences; if (onlyDiffs != null && onlyDiffs.Count > 0) { foreach (var diff in onlyDiffs) { string content = diff.content?.ToString() ?? ""; string type = diff.typeName?.ToString() ?? ""; int lineNumber = diff.lineNumber; switch (type) { case "Deleted": sb.AppendLine($"Removido (linha {lineNumber}):"); sb.AppendLine($"- {content}"); break; case "Inserted": sb.AppendLine($"Adicionado (linha {lineNumber}):"); sb.AppendLine($"+ {content}"); break; } sb.AppendLine(); } } else { sb.AppendLine("Nenhuma diferença significativa encontrada entre os documentos."); } } catch (Exception ex) { sb.AppendLine("Erro ao processar diferenças. Resumo simplificado:"); sb.AppendLine("As diferenças entre os documentos não puderam ser formatadas adequadamente."); } return sb.ToString(); } } public class AuthenticateRequest { public string UserId { get; set; } public string Company { get; set; } public string Name { get; set; } } public class NewClientResponse { public string Secret { get; set; } } public class TokenResponse { public string Token { get; set; } } }