using CMSMicroservice.Protobuf.Protos.DiscountProduct;
using CMSMicroservice.Protobuf.Protos.DiscountCategory;
using Google.Protobuf.WellKnownTypes;

namespace FrontOffice.Main.Utilities;

// ── DTOs ──
public record DiscountProductCard(
    long Id,
    string Title,
    string ShortInfo,
    long Price,
    int MaxDiscountPercent,
    string ImageUrl,
    string ThumbnailUrl,
    int RemainingCount,
    int ViewCount,
    bool IsActive,
    DateTime Created);

public record DiscountProductDetail(
    long Id,
    string Title,
    string ShortInfo,
    string FullInfo,
    long Price,
    int MaxDiscountPercent,
    string ImageUrl,
    string ThumbnailUrl,
    int RemainingCount,
    int ViewCount,
    int SortOrder,
    bool IsActive,
    List<DiscountCategoryInfo> Categories,
    List<DiscountProductImageDto> Images,
    DateTime Created);

public record DiscountCategoryInfo(long Id, string Name, string Title);

public record DiscountProductImageDto(
    long Id,
    string ImageUrl,
    string ThumbnailUrl,
    string? Title,
    string? AltText,
    int SortOrder);

public record DiscountCategoryNode(
    long Id,
    string Name,
    string Title,
    string? Description,
    string? ImagePath,
    long? ParentCategoryId,
    int SortOrder,
    bool IsActive,
    int ProductCount,
    List<DiscountCategoryNode> Children);

public record DiscountProductListResult(
    List<DiscountProductCard> Products,
    int TotalCount,
    int TotalPages,
    int CurrentPage);

// ── Service ──
public class DiscountProductService
{
    private readonly DiscountProductContract.DiscountProductContractClient _productClient;
    private readonly DiscountCategoryContract.DiscountCategoryContractClient _categoryClient;

    public DiscountProductService(
        DiscountProductContract.DiscountProductContractClient productClient,
        DiscountCategoryContract.DiscountCategoryContractClient categoryClient)
    {
        _productClient = productClient;
        _categoryClient = categoryClient;
    }

    public async Task<DiscountProductListResult> GetProductsAsync(
        int page = 1, int pageSize = 12,
        string? search = null, long? categoryId = null,
        bool? inStock = null, string? sortBy = null)
    {
        try
        {
            var request = new GetDiscountProductsRequest
            {
                PageNumber = page,
                PageSize = pageSize,
                IsActive = true // فقط محصولات فعال
            };

            if (!string.IsNullOrWhiteSpace(search))
                request.SearchQuery = search;
            if (categoryId.HasValue)
                request.CategoryId = categoryId.Value;
            if (inStock.HasValue)
                request.InStock = inStock.Value;
            if (!string.IsNullOrWhiteSpace(sortBy))
                request.SortBy = sortBy;

            var response = await _productClient.GetDiscountProductsAsync(request);

            var products = response.Models.Select(m => new DiscountProductCard(
                Id: m.Id,
                Title: m.Title ?? string.Empty,
                ShortInfo: m.ShortInfomation ?? string.Empty,
                Price: m.Price,
                MaxDiscountPercent: m.MaxDiscountPercent,
                ImageUrl: BuildUrl(m.ImagePath),
                ThumbnailUrl: BuildUrl(m.ThumbnailPath),
                RemainingCount: m.RemainingCount,
                ViewCount: m.ViewCount,
                IsActive: m.IsActive,
                Created: m.Created?.ToDateTime() ?? DateTime.MinValue
            )).ToList();

            var totalCount = (int)(response.MetaData?.TotalCount ?? 0);
            var totalPages = (int)(response.MetaData?.TotalPage ?? 0);

            return new DiscountProductListResult(products, totalCount, totalPages, page);
        }
        catch
        {
            return new DiscountProductListResult(new(), 0, 0, page);
        }
    }

    public Task<DiscountProductListResult> GetTopSellingAsync(int count = 6, bool? inStock = null)
        => GetProductsAsync(page: 1, pageSize: count, sortBy: "SaleCount desc", inStock: inStock);

    public async Task<DiscountProductDetail?> GetByIdAsync(long productId)
    {
        try
        {
            var response = await _productClient.GetDiscountProductByIdAsync(
                new GetDiscountProductByIdRequest { ProductId = productId });

            var categories = response.Categories
                .Select(c => new DiscountCategoryInfo(c.Id, c.Name ?? "", c.Title ?? ""))
                .ToList();

            // Load images
            var imagesResponse = await _productClient.GetDiscountProductImagesAsync(
                new GetDiscountProductImagesRequest { DiscountProductId = productId, OnlyActive = true });

            var images = imagesResponse.Images
                .OrderBy(i => i.SortOrder)
                .Select(i => new DiscountProductImageDto(
                    Id: i.Id,
                    ImageUrl: BuildUrl(i.ImagePath),
                    ThumbnailUrl: BuildUrl(i.ThumbnailPath),
                    Title: i.Title,
                    AltText: i.AltText,
                    SortOrder: i.SortOrder))
                .ToList();

            return new DiscountProductDetail(
                Id: response.Id,
                Title: response.Title ?? string.Empty,
                ShortInfo: response.ShortInfomation ?? string.Empty,
                FullInfo: response.FullInformation ?? string.Empty,
                Price: response.Price,
                MaxDiscountPercent: response.MaxDiscountPercent,
                ImageUrl: BuildUrl(response.ImagePath),
                ThumbnailUrl: BuildUrl(response.ThumbnailPath),
                RemainingCount: response.RemainingCount,
                ViewCount: response.ViewCount,
                SortOrder: response.SortOrder,
                IsActive: response.IsActive,
                Categories: categories,
                Images: images,
                Created: response.Created?.ToDateTime() ?? DateTime.MinValue);
        }
        catch
        {
            return null;
        }
    }

    public async Task<List<DiscountCategoryNode>> GetCategoriesAsync(bool onlyActive = true)
    {
        try
        {
            var request = new GetDiscountCategoriesRequest();
            if (onlyActive) request.IsActive = true;

            var response = await _categoryClient.GetDiscountCategoriesAsync(request);
            return response.Categories.Select(MapCategory).ToList();
        }
        catch
        {
            return new();
        }
    }

    private static DiscountCategoryNode MapCategory(DiscountCategoryDto dto) => new(
        Id: dto.Id,
        Name: dto.Name ?? "",
        Title: dto.Title ?? "",
        Description: dto.Description,
        ImagePath: dto.ImagePath,
        ParentCategoryId: dto.ParentCategoryId,
        SortOrder: dto.SortOrder,
        IsActive: dto.IsActive,
        ProductCount: dto.ProductCount,
        Children: dto.Children.Select(MapCategory).ToList());

    private static string BuildUrl(string? path)
        => path ?? string.Empty;
}
