using Microsoft.EntityFrameworkCore; using ProposalSystem.Application.DTOs; using ProposalSystem.Application.Interfaces; using ProposalSystem.Domain.Entities; using ProposalSystem.Infrastructure.Data; namespace ProposalSystem.Infrastructure.Services; public class SimilarProposalService : ISimilarProposalService { private readonly ProposalDbContext _db; private readonly ICurrentUserService _currentUser; public SimilarProposalService(ProposalDbContext db, ICurrentUserService currentUser) { _db = db; _currentUser = currentUser; } public async Task> GetSimilarProposalsAsync( Guid proposalId, CancellationToken ct = default) { var references = await _db.SimilarProposalReferences .Where(r => r.ProposalId == proposalId) .OrderByDescending(r => r.SimilarityScore) .Take(5) .ToListAsync(ct); if (references.Count == 0) return []; var libraryItemIds = references.Select(r => r.ReferencedLibraryItemId).ToList(); var proposals = await _db.Proposals .Include(p => p.LineItems) .Where(p => libraryItemIds.Contains(p.ProposalNumber)) .ToListAsync(ct); var proposalsByNumber = proposals.ToDictionary(p => p.ProposalNumber); var results = new List(); foreach (var reference in references) { if (!proposalsByNumber.TryGetValue(reference.ReferencedLibraryItemId, out var referencedProposal)) continue; results.Add(new SimilarProposalResponse( referencedProposal.ProposalNumber, referencedProposal.CustomerName, referencedProposal.ServiceCategory.ToString(), reference.SimilarityScore, referencedProposal.TotalBidAmount, referencedProposal.LineItems .OrderBy(li => li.SortOrder) .Select(li => new SimilarLineItemResponse( li.Description, li.Quantity, li.Unit, li.UnitPrice, li.TotalPrice )) .ToList() )); } return results; } public async Task AddReferenceAsync( Guid proposalId, CreateSimilarReferenceRequest request, CancellationToken ct = default) { var reference = new SimilarProposalReference { Id = Guid.NewGuid(), ProposalId = proposalId, ReferencedLibraryItemId = request.ReferencedLibraryItemId, SimilarityScore = request.SimilarityScore, ReferencedAt = DateTime.UtcNow, ReferencedById = _currentUser.UserId, }; _db.SimilarProposalReferences.Add(reference); await _db.SaveChangesAsync(ct); } }