using CMSMicroservice.Application.Common.Interfaces;

namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWeekDefinitions;

/// <summary>
/// Handler برای دریافت لیست هفته‌ها از کش
/// </summary>
public class GetWeekDefinitionsQueryHandler : IRequestHandler<GetWeekDefinitionsQuery, GetWeekDefinitionsResponseDto>
{
    private readonly IWeekDefinitionRepository _weekDefinitionRepository;

    public GetWeekDefinitionsQueryHandler(IWeekDefinitionRepository weekDefinitionRepository)
    {
        _weekDefinitionRepository = weekDefinitionRepository;
    }

    public Task<GetWeekDefinitionsResponseDto> Handle(
        GetWeekDefinitionsQuery request, 
        CancellationToken cancellationToken)
    {
        // گرفتن همه هفته‌ها از کش
        var allWeeks = _weekDefinitionRepository.GetAllWeeks();
        
        // اعمال فیلترها
        var filteredWeeks = allWeeks.AsEnumerable();
        
        if (request.Filter != null)
        {
            var filter = request.Filter;
            
            // جستجوی متنی روی DisplayName
            if (!string.IsNullOrWhiteSpace(filter.SearchText))
            {
                filteredWeeks = filteredWeeks.Where(w => 
                    w.DisplayName.Contains(filter.SearchText, StringComparison.OrdinalIgnoreCase));
            }
            
            // فیلتر بر اساس WeekOrder
            if (filter.WeekOrder.HasValue)
            {
                filteredWeeks = filteredWeeks.Where(w => w.WeekOrder == filter.WeekOrder.Value);
            }
            
            // فیلتر بر اساس GregorianWeekNumber
            if (!string.IsNullOrWhiteSpace(filter.GregorianWeekNumber))
            {
                filteredWeeks = filteredWeeks.Where(w => 
                    w.GregorianWeekNumber == filter.GregorianWeekNumber);
            }
            
            // فیلتر بر اساس PersianWeekNumber
            if (!string.IsNullOrWhiteSpace(filter.PersianWeekNumber))
            {
                filteredWeeks = filteredWeeks.Where(w => 
                    w.PersianWeekNumber == filter.PersianWeekNumber);
            }
            
            // فیلتر بر اساس سال میلادی
            if (filter.GregorianYear.HasValue)
            {
                filteredWeeks = filteredWeeks.Where(w => w.GregorianYear == filter.GregorianYear.Value);
            }
            
            // فیلتر بر اساس سال شمسی
            if (filter.PersianYear.HasValue)
            {
                filteredWeeks = filteredWeeks.Where(w => w.PersianYear == filter.PersianYear.Value);
            }
            
            // فیلتر بر اساس فعال بودن
            if (filter.IsActive.HasValue)
            {
                filteredWeeks = filteredWeeks.Where(w => w.IsActive == filter.IsActive.Value);
            }
        }
        
        // مرتب‌سازی
        filteredWeeks = request.SortBy?.ToLower() switch
        {
            "weekorder_desc" => filteredWeeks.OrderByDescending(w => w.WeekOrder),
            "displayname" => filteredWeeks.OrderBy(w => w.DisplayName),
            "displayname_desc" => filteredWeeks.OrderByDescending(w => w.DisplayName),
            "startdate" => filteredWeeks.OrderBy(w => w.StartDate),
            "startdate_desc" => filteredWeeks.OrderByDescending(w => w.StartDate),
            _ => filteredWeeks.OrderBy(w => w.WeekOrder) // پیش‌فرض: weekorder
        };
        
        // تعداد کل قبل از صفحه‌بندی
        var weeksList = filteredWeeks.ToList();
        var totalCount = weeksList.Count;
        
        // صفحه‌بندی
        if (request.PaginationState != null)
        {
            var pageNumber = request.PaginationState.PageNumber > 0 ? request.PaginationState.PageNumber : 1;
            var pageSize = request.PaginationState.PageSize > 0 ? request.PaginationState.PageSize : 20;
            
            weeksList = weeksList
                .Skip((pageNumber - 1) * pageSize)
                .Take(pageSize)
                .ToList();
        }
        
        // گرفتن هفته جاری برای مشخص کردن IsCurrentWeek
        var currentWeek = _weekDefinitionRepository.GetCurrentWeek();
        
        // تبدیل به DTO
        var weekDtos = weeksList.Select(w => new WeekDefinitionItemDto
        {
            Id = w.Id,
            WeekOrder = w.WeekOrder,
            DisplayName = w.DisplayName,
            GregorianWeekNumber = w.GregorianWeekNumber,
            PersianWeekNumber = w.PersianWeekNumber,
            StartDate = w.StartDate,
            EndDate = w.EndDate,
            GregorianYear = w.GregorianYear,
            PersianYear = w.PersianYear,
            IsActive = w.IsActive,
            IsCurrentWeek = currentWeek != null && w.WeekOrder == currentWeek.WeekOrder
        }).ToList();

        var response = new GetWeekDefinitionsResponseDto
        {
            Data = weekDtos,
            TotalCount = totalCount
        };

        return Task.FromResult(response);
    }
}
