namespace BackOffice.Services.Tag;

public class TagService : ITagService
{
    private readonly CMSMicroservice.Protobuf.Protos.Tag.TagContract.TagContractClient _tagClient;
    private readonly CMSMicroservice.Protobuf.Protos.ProductTag.ProductTagContract.ProductTagContractClient _productTagClient;
    private readonly CMSMicroservice.Protobuf.Protos.Products.ProductsContract.ProductsContractClient _productsClient;
    public TagService(
        CMSMicroservice.Protobuf.Protos.Tag.TagContract.TagContractClient tagClient,
        CMSMicroservice.Protobuf.Protos.ProductTag.ProductTagContract.ProductTagContractClient productTagClient,
        CMSMicroservice.Protobuf.Protos.Products.ProductsContract.ProductsContractClient productsClient)
    {
        _tagClient = tagClient;
        _productTagClient = productTagClient;
        _productsClient = productsClient;
    }

    public async Task<TagListResultDto> GetTagsAsync(TagFilterDto filter)
    {
        var request = new CMSMicroservice.Protobuf.Protos.Tag.GetAllTagByFilterRequest
        {
            PaginationState = new CMSMicroservice.Protobuf.Protos.PaginationState
            {
                PageNumber = filter.PageNumber,
                PageSize = filter.PageSize
            },
            Filter = new CMSMicroservice.Protobuf.Protos.Tag.GetAllTagByFilterFilter()
        };

        if (!string.IsNullOrWhiteSpace(filter.SearchTerm))
        {
            request.Filter.Name = filter.SearchTerm;
            request.Filter.Title = filter.SearchTerm;
        }

        if (filter.IsActive.HasValue)
        {
            request.Filter.IsActive = filter.IsActive.Value;
        }

        var response = await _tagClient.GetAllTagByFilterAsync(request);

        var result = new TagListResultDto
        {
            TotalCount = response.MetaData != null ? (int)response.MetaData.TotalCount : response.Models.Count
        };

        foreach (var model in response.Models)
        {
            result.Items.Add(new TagListItemDto
            {
                Id = model.Id,
                Name = model.Name,
                Title = model.Title,
                Description = model.Description,
                IsActive = model.IsActive,
                SortOrder = model.SortOrder
            });
        }

        return result;
    }

    public async Task<TagDetailsDto?> GetByIdAsync(long id)
    {
        var response = await _tagClient.GetTagAsync(new CMSMicroservice.Protobuf.Protos.Tag.GetTagRequest { Id = id });

        if (response == null || response.Id <= 0)
        {
            return null;
        }

        return new TagDetailsDto
        {
            Id = response.Id,
            Name = response.Name,
            Title = response.Title,
            Description = response.Description,
            IsActive = response.IsActive,
            SortOrder = response.SortOrder
        };
    }

    public async Task<long> CreateAsync(TagEditDto dto)
    {
        var request = new CMSMicroservice.Protobuf.Protos.Tag.CreateNewTagRequest
        {
            Name = dto.Name,
            Title = dto.Title,
            Description = dto.Description ?? string.Empty,
            IsActive = dto.IsActive,
            SortOrder = dto.SortOrder
        };

        var response = await _tagClient.CreateNewTagAsync(request);
        return response.Id;
    }

    public async Task UpdateAsync(long id, TagEditDto dto)
    {
        var request = new CMSMicroservice.Protobuf.Protos.Tag.UpdateTagRequest
        {
            Id = id,
            Name = dto.Name,
            Title = dto.Title,
            Description = dto.Description ?? string.Empty,
            IsActive = dto.IsActive,
            SortOrder = dto.SortOrder
        };

        await _tagClient.UpdateTagAsync(request);
    }

    public async Task DeleteAsync(long id)
    {
        await _tagClient.DeleteTagAsync(new CMSMicroservice.Protobuf.Protos.Tag.DeleteTagRequest { Id = id });
    }

    public async Task AssignToProductAsync(long productId, long tagId)
    {
        var request = new CMSMicroservice.Protobuf.Protos.ProductTag.CreateNewProductTagRequest
        {
            ProductId = productId,
            TagId = tagId
        };

        await _productTagClient.CreateNewProductTagAsync(request);
    }

    public async Task<List<ProductTagViewDto>> GetProductTagsAsync(long productId)
    {
        var request = new CMSMicroservice.Protobuf.Protos.ProductTag.GetAllProductTagByFilterRequest
        {
            PaginationState = new CMSMicroservice.Protobuf.Protos.PaginationState
            {
                PageNumber = 1,
                PageSize = 100
            },
            Filter = new CMSMicroservice.Protobuf.Protos.ProductTag.GetAllProductTagByFilterFilter
            {
                ProductId = productId
            }
        };

        var response = await _productTagClient.GetAllProductTagByFilterAsync(request);

        var tagIds = response.Models.Select(m => m.TagId).Distinct().ToList();

        // دریافت عنوان واقعی تگ‌ها از سرویس تگ
        var tagTitleMap = new Dictionary<long, string>();
        foreach (var tagId in tagIds)
        {
            try
            {
                var tagResponse = await _tagClient.GetTagAsync(
                    new CMSMicroservice.Protobuf.Protos.Tag.GetTagRequest { Id = tagId });
                if (tagResponse != null && !string.IsNullOrWhiteSpace(tagResponse.Title))
                {
                    tagTitleMap[tagId] = tagResponse.Title;
                }
            }
            catch
            {
                // اگر تگ پیدا نشد، از شناسه استفاده می‌شود
            }
        }

        var tagsResult = new List<ProductTagViewDto>();

        foreach (var model in response.Models)
        {
            tagsResult.Add(new ProductTagViewDto
            {
                ProductTagId = model.Id,
                TagId = model.TagId,
                TagTitle = tagTitleMap.TryGetValue(model.TagId, out var title) ? title : $"تگ #{model.TagId}"
            });
        }

        return tagsResult;
    }

    public async Task RemoveProductTagAsync(long productTagId)
    {
        await _productTagClient.DeleteProductTagAsync(
            new CMSMicroservice.Protobuf.Protos.ProductTag.DeleteProductTagRequest
            {
                Id = productTagId
            });
    }
}
