using EonaCat.Logger.Server.Data;
using EonaCat.Logger.Server.Models;
using Microsoft.EntityFrameworkCore;

namespace EonaCat.Logger.Server.Services;

public interface ISearchService
{
    Task<SearchResult> SearchAsync(SearchRequest request);
}

public class SearchRequest
{
    public string Query { get; set; } = string.Empty;
    public List<string>? Applications { get; set; }
    public List<string>? Environments { get; set; }
    public List<int>? Levels { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public int Limit { get; set; } = 100;
}

public class SearchResult
{
    public List<LogEntry> Results { get; set; } = new();
    public int TotalCount { get; set; }
    public Dictionary<string, int> Facets { get; set; } = new();
}

public class SearchService : ISearchService
{
    private readonly LoggerDbContext _context;

    public SearchService(LoggerDbContext context)
    {
        _context = context;
    }

    public async Task<SearchResult> SearchAsync(SearchRequest request)
    {
        var query = _context.LogEntries.AsQueryable();

        if (!string.IsNullOrEmpty(request.Query))
        {
            var search = request.Query.ToLower();
            query = query.Where(l =>
                l.Message.ToLower().Contains(search) ||
                (l.Exception != null && l.Exception.ToLower().Contains(search)) ||
                (l.StackTrace != null && l.StackTrace.ToLower().Contains(search)) ||
                l.Category.ToLower().Contains(search) ||
                l.ApplicationName.ToLower().Contains(search) ||
                (l.UserId != null && l.UserId.ToLower().Contains(search)) ||
                (l.CorrelationId != null && l.CorrelationId.ToLower().Contains(search)));
        }

        if (request.Applications?.Any() == true)
            query = query.Where(l => request.Applications.Contains(l.ApplicationName));

        if (request.Environments?.Any() == true)
            query = query.Where(l => request.Environments.Contains(l.Environment));

        if (request.Levels?.Any() == true)
            query = query.Where(l => request.Levels.Contains(l.Level));

        if (request.StartDate.HasValue)
            query = query.Where(l => l.Timestamp >= request.StartDate.Value);

        if (request.EndDate.HasValue)
            query = query.Where(l => l.Timestamp <= request.EndDate.Value);

        var totalCount = await query.CountAsync();
        var results = await query
            .OrderByDescending(l => l.Timestamp)
            .Take(request.Limit)
            .ToListAsync();

        var facets = await query
            .GroupBy(l => l.Level)
            .Select(g => new { Level = g.Key, Count = g.Count() })
            .ToDictionaryAsync(x => $"Level_{x.Level}", x => x.Count);

        return new SearchResult
        {
            Results = results,
            TotalCount = totalCount,
            Facets = facets
        };
    }
}