using CMSMicroservice.Application.Common.Interfaces;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace CMSMicroservice.Application.DiscountShopCQ.Queries.GetDiscountCategories;

public class GetDiscountCategoriesQueryHandler : IRequestHandler<GetDiscountCategoriesQuery, GetDiscountCategoriesResponseDto>
{
    private readonly IApplicationDbContext _context;

    public GetDiscountCategoriesQueryHandler(IApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<GetDiscountCategoriesResponseDto> Handle(GetDiscountCategoriesQuery request, CancellationToken cancellationToken)
    {
        var query = _context.DiscountCategories.AsQueryable();

        // فیلتر بر اساس ParentCategoryId
        if (request.ParentCategoryId.HasValue)
        {
            query = query.Where(c => c.ParentCategoryId == request.ParentCategoryId.Value);
        }
        else
        {
            // اگر ParentCategoryId مشخص نشده، فقط دسته‌های اصلی (بدون والد) را برگردان
            query = query.Where(c => c.ParentCategoryId == null);
        }

        // فیلتر بر اساس وضعیت فعال
        if (request.IsActive.HasValue)
        {
            query = query.Where(c => c.IsActive == request.IsActive.Value);
        }

        var categories = await query
            .OrderBy(c => c.SortOrder)
            .ThenBy(c => c.Title)
            .Select(c => new DiscountCategoryDto
            {
                Id = c.Id,
                Name = c.Name,
                Title = c.Title,
                Description = c.Description,
                ImagePath = c.ImagePath,
                ParentCategoryId = c.ParentCategoryId,
                SortOrder = c.SortOrder,
                IsActive = c.IsActive,
                ProductCount = _context.DiscountProductCategories.Count(pc => pc.CategoryId == c.Id)
            })
            .ToListAsync(cancellationToken);

        // بارگذاری زیرمجموعه‌ها به صورت بازگشتی
        foreach (var category in categories)
        {
            category.Children = await LoadChildren(category.Id, request.IsActive, cancellationToken);
        }

        return new GetDiscountCategoriesResponseDto
        {
            Categories = categories
        };
    }

    private async Task<List<DiscountCategoryDto>> LoadChildren(long parentId, bool? isActive, CancellationToken cancellationToken)
    {
        var query = _context.DiscountCategories.Where(c => c.ParentCategoryId == parentId);

        if (isActive.HasValue)
        {
            query = query.Where(c => c.IsActive == isActive.Value);
        }

        var children = await query
            .OrderBy(c => c.SortOrder)
            .ThenBy(c => c.Title)
            .Select(c => new DiscountCategoryDto
            {
                Id = c.Id,
                Name = c.Name,
                Title = c.Title,
                Description = c.Description,
                ImagePath = c.ImagePath,
                ParentCategoryId = c.ParentCategoryId,
                SortOrder = c.SortOrder,
                IsActive = c.IsActive,
                ProductCount = _context.DiscountProductCategories.Count(pc => pc.CategoryId == c.Id)
            })
            .ToListAsync(cancellationToken);

        foreach (var child in children)
        {
            child.Children = await LoadChildren(child.Id, isActive, cancellationToken);
        }

        return children;
    }
}
