using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using UniVerse.Application.Interfaces; using UniVerse.Domain.Enums; using UniVerse.Infrastructure.Data; namespace UniVerse.Infrastructure.Services; public class LlmAnalysisService : ILlmAnalysisService { private readonly AppDbContext _db; private readonly ILlmClient _llm; private readonly IGamificationService _gamification; private readonly ILogger _logger; public LlmAnalysisService(AppDbContext db, ILlmClient llm, IGamificationService gamification, ILogger logger) { _db = db; _llm = llm; _gamification = gamification; _logger = logger; } public async Task AnalyzeReviewAsync(int reviewId) { var review = await _db.Reviews.Include(r => r.Lecture) .FirstOrDefaultAsync(r => r.Id == reviewId); if (review == null || review.LlmStatus != ReviewLlmStatus.Pending) return; try { var context = $"Lecture: {review.Lecture?.Title}"; var result = await _llm.AnalyzeReviewAsync(review.Text ?? "", context); review.QualityScore = result.QualityScore; review.Sentiment = ParseSentiment(result.Sentiment); review.LlmTags = result.Tags; review.IsInformative = result.IsInformative; review.LlmRawOutput = result.RawOutput; review.LlmStatus = ReviewLlmStatus.Analyzed; review.UpdatedAt = DateTime.UtcNow; await _db.SaveChangesAsync(); if (result.IsInformative) await _gamification.AwardCoinsAsync(review.UserId, 10, CoinTransactionType.ReviewReward, reviewId: review.Id, description: "Informative review reward"); await _gamification.CheckAndAwardAchievementsAsync(review.UserId); _logger.LogInformation("Review {ReviewId} analyzed successfully", reviewId); } catch (Exception ex) { _logger.LogWarning(ex, "Failed to analyze review {ReviewId}, will retry later", reviewId); } } private static ReviewSentiment ParseSentiment(string value) { var normalized = value.Trim().ToLowerInvariant(); return normalized switch { "positive" or "положительный" or "положительная" or "позитивный" or "позитивная" => ReviewSentiment.Positive, "negative" or "отрицательный" or "отрицательная" or "негативный" or "негативная" => ReviewSentiment.Negative, "neutral" or "нейтральный" or "нейтральная" => ReviewSentiment.Neutral, _ when Enum.TryParse(value, true, out var sentiment) => sentiment, _ => ReviewSentiment.Neutral }; } }