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<LlmAnalysisService> _logger;

    public LlmAnalysisService(AppDbContext db, ILlmClient llm,
        IGamificationService gamification, ILogger<LlmAnalysisService> 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<ReviewSentiment>(value, true, out var sentiment) => sentiment,
            _ => ReviewSentiment.Neutral
        };
    }
}
