using CMSMicroservice.Protobuf.Protos.BlogCategory;
using CMSMicroservice.WebApi.Common.Services;
using CMSMicroservice.Application.BlogCategoryCQ.Commands.CreateBlogCategory;
using CMSMicroservice.Application.BlogCategoryCQ.Commands.UpdateBlogCategory;
using CMSMicroservice.Application.BlogCategoryCQ.Commands.DeleteBlogCategory;
using CMSMicroservice.Application.BlogCategoryCQ.Queries.GetBlogCategory;
using CMSMicroservice.Application.BlogCategoryCQ.Queries.GetAllBlogCategories;
using CMSMicroservice.Application.BlogCategoryCQ.Queries.GetActiveBlogCategories;
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using Mapster;
using MediatR;
using AppModels = CMSMicroservice.Application.Common.Models;
using ProtoMetaData = CMSMicroservice.Protobuf.Protos.MetaData;

namespace CMSMicroservice.WebApi.Services;

public class BlogCategoryService : BlogCategoryContract.BlogCategoryContractBase
{
    private readonly ISender _sender;
    private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;

    public BlogCategoryService(ISender sender, IDispatchRequestToCQRS dispatchRequestToCQRS)
    {
        _sender = sender;
        _dispatchRequestToCQRS = dispatchRequestToCQRS;
    }

    public override async Task<CreateBlogCategoryResponse> CreateBlogCategory(CreateBlogCategoryRequest request, ServerCallContext context)
    {
        return await _dispatchRequestToCQRS.Handle<CreateBlogCategoryRequest, CreateBlogCategoryCommand, CreateBlogCategoryResponse>(request, context);
    }

    public override async Task<Empty> UpdateBlogCategory(UpdateBlogCategoryRequest request, ServerCallContext context)
    {
        return await _dispatchRequestToCQRS.Handle<UpdateBlogCategoryRequest, UpdateBlogCategoryCommand>(request, context);
    }

    public override async Task<Empty> DeleteBlogCategory(DeleteBlogCategoryRequest request, ServerCallContext context)
    {
        return await _dispatchRequestToCQRS.Handle<DeleteBlogCategoryRequest, DeleteBlogCategoryCommand>(request, context);
    }

    public override async Task<GetBlogCategoryResponse> GetBlogCategory(GetBlogCategoryRequest request, ServerCallContext context)
    {
        var query = new GetBlogCategoryQuery { Id = request.Id };
        var result = await _sender.Send(query, context.CancellationToken);
        return MapCategoryToResponse(result);
    }

    public override async Task<GetAllBlogCategoriesResponse> GetAllBlogCategories(GetAllBlogCategoriesRequest request, ServerCallContext context)
    {
        var query = new GetAllBlogCategoriesQuery
        {
            PageNumber = request.PaginationState?.PageNumber ?? 1,
            PageSize = request.PaginationState?.PageSize ?? 20,
            SearchTerm = request.SortBy
        };

        var result = await _sender.Send(query, context.CancellationToken);
        var response = new GetAllBlogCategoriesResponse
        {
            MetaData = result.MetaData.Adapt<ProtoMetaData>()
        };

        foreach (var item in result.Models)
            response.Models.Add(MapToListItem(item));

        return response;
    }

    public override async Task<GetActiveBlogCategoriesResponse> GetActiveBlogCategories(GetActiveBlogCategoriesRequest request, ServerCallContext context)
    {
        var query = new GetActiveBlogCategoriesQuery();
        var result = await _sender.Send(query, context.CancellationToken);

        var response = new GetActiveBlogCategoriesResponse();
        foreach (var item in result)
            response.Categories.Add(MapToListItem(item));

        return response;
    }

    // ── Private Mapping Helpers ──

    private static GetBlogCategoryResponse MapCategoryToResponse(BlogCategoryDto dto)
    {
        return new GetBlogCategoryResponse
        {
            Id = dto.Id,
            Title = dto.Title ?? string.Empty,
            Slug = dto.Slug ?? string.Empty,
            Description = dto.Description,
            IconName = dto.IconName,
            SortOrder = dto.SortOrder,
            IsActive = dto.IsActive,
            PostCount = dto.PostCount,
            Created = dto.Created != default ? Timestamp.FromDateTime(DateTime.SpecifyKind(dto.Created, DateTimeKind.Utc)) : null
        };
    }

    private static BlogCategoryListItem MapToListItem(BlogCategoryDto dto)
    {
        return new BlogCategoryListItem
        {
            Id = dto.Id,
            Title = dto.Title ?? string.Empty,
            Slug = dto.Slug ?? string.Empty,
            Description = dto.Description,
            IconName = dto.IconName,
            SortOrder = dto.SortOrder,
            IsActive = dto.IsActive,
            PostCount = dto.PostCount
        };
    }
}
