using AutoMapper;
using PowderCoating.Application.DTOs.Catalog;
using PowderCoating.Core.Entities;
using System.Collections.Generic;
using System.Linq;

namespace PowderCoating.Application.Mappings
{
    /// <summary>
    /// AutoMapper profile for product catalog entities.
    /// </summary>
    public class CatalogProfile : Profile
    {
        public CatalogProfile()
        {
            // ==================== Category Mappings ====================

            // Category -> CategoryDto
            CreateMap<CatalogCategory, CategoryDto>()
                .ForMember(dest => dest.ParentCategoryName,
                    opt => opt.MapFrom(src => src.ParentCategory != null ? src.ParentCategory.Name : null))
                .ForMember(dest => dest.ItemCount,
                    opt => opt.MapFrom(src => src.Items.Count(i => !i.IsDeleted)))
                .ForMember(dest => dest.SubCategoryCount,
                    opt => opt.MapFrom(src => src.SubCategories.Count(c => !c.IsDeleted)));

            // CreateCategoryDto -> CatalogCategory
            CreateMap<CreateCategoryDto, CatalogCategory>()
                .ForMember(dest => dest.Id, opt => opt.Ignore())
                .ForMember(dest => dest.CompanyId, opt => opt.Ignore())
                .ForMember(dest => dest.CreatedAt, opt => opt.Ignore())
                .ForMember(dest => dest.UpdatedAt, opt => opt.Ignore())
                .ForMember(dest => dest.CreatedBy, opt => opt.Ignore())
                .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore())
                .ForMember(dest => dest.IsDeleted, opt => opt.Ignore())
                .ForMember(dest => dest.ParentCategory, opt => opt.Ignore())
                .ForMember(dest => dest.SubCategories, opt => opt.Ignore())
                .ForMember(dest => dest.Items, opt => opt.Ignore());

            // CatalogCategory -> UpdateCategoryDto (reverse mapping for Edit GET)
            CreateMap<CatalogCategory, UpdateCategoryDto>();

            // UpdateCategoryDto -> CatalogCategory
            CreateMap<UpdateCategoryDto, CatalogCategory>()
                .ForMember(dest => dest.CompanyId, opt => opt.Ignore())
                .ForMember(dest => dest.CreatedAt, opt => opt.Ignore())
                .ForMember(dest => dest.UpdatedAt, opt => opt.Ignore())
                .ForMember(dest => dest.CreatedBy, opt => opt.Ignore())
                .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore())
                .ForMember(dest => dest.IsDeleted, opt => opt.Ignore())
                .ForMember(dest => dest.ParentCategory, opt => opt.Ignore())
                .ForMember(dest => dest.SubCategories, opt => opt.Ignore())
                .ForMember(dest => dest.Items, opt => opt.Ignore());

            // CatalogCategory -> CategoryTreeDto (recursive)
            CreateMap<CatalogCategory, CategoryTreeDto>()
                .ForMember(dest => dest.ItemCount,
                    opt => opt.MapFrom(src => src.Items.Count(i => !i.IsDeleted)))
                .ForMember(dest => dest.HasItems,
                    opt => opt.MapFrom(src => src.Items.Any(i => !i.IsDeleted)))
                .ForMember(dest => dest.Children,
                    opt => opt.MapFrom(src => src.SubCategories.Where(c => !c.IsDeleted).OrderBy(c => c.DisplayOrder)));

            // ==================== Item Mappings ====================

            // CatalogItem -> CatalogItemDto
            CreateMap<CatalogItem, CatalogItemDto>()
                .ForMember(dest => dest.CategoryName,
                    opt => opt.MapFrom(src => src.Category.Name))
                .ForMember(dest => dest.FullCategoryPath,
                    opt => opt.MapFrom(src => GetCategoryPath(src.Category)))
                .ForMember(dest => dest.RevenueAccountName,
                    opt => opt.MapFrom(src => src.RevenueAccount != null
                        ? $"{src.RevenueAccount.AccountNumber} – {src.RevenueAccount.Name}" : null))
                .ForMember(dest => dest.CogsAccountName,
                    opt => opt.MapFrom(src => src.CogsAccount != null
                        ? $"{src.CogsAccount.AccountNumber} – {src.CogsAccount.Name}" : null));

            // CatalogItem -> CatalogItemListDto
            CreateMap<CatalogItem, CatalogItemListDto>()
                .ForMember(dest => dest.CategoryName,
                    opt => opt.MapFrom(src => src.Category.Name));

            // CreateCatalogItemDto -> CatalogItem
            CreateMap<CreateCatalogItemDto, CatalogItem>()
                .ForMember(dest => dest.Id, opt => opt.Ignore())
                .ForMember(dest => dest.CompanyId, opt => opt.Ignore())
                .ForMember(dest => dest.CreatedAt, opt => opt.Ignore())
                .ForMember(dest => dest.UpdatedAt, opt => opt.Ignore())
                .ForMember(dest => dest.CreatedBy, opt => opt.Ignore())
                .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore())
                .ForMember(dest => dest.IsDeleted, opt => opt.Ignore())
                .ForMember(dest => dest.Category, opt => opt.Ignore())
                .ForMember(dest => dest.RevenueAccount, opt => opt.Ignore())
                .ForMember(dest => dest.CogsAccount, opt => opt.Ignore())
                // Image paths are set by CatalogImageService after the entity is saved, not from the DTO.
                .ForMember(dest => dest.ImagePath, opt => opt.Ignore())
                .ForMember(dest => dest.ThumbnailPath, opt => opt.Ignore());

            // UpdateCatalogItemDto -> CatalogItem
            CreateMap<UpdateCatalogItemDto, CatalogItem>()
                .ForMember(dest => dest.CompanyId, opt => opt.Ignore())
                .ForMember(dest => dest.CreatedAt, opt => opt.Ignore())
                .ForMember(dest => dest.UpdatedAt, opt => opt.Ignore())
                .ForMember(dest => dest.CreatedBy, opt => opt.Ignore())
                .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore())
                .ForMember(dest => dest.IsDeleted, opt => opt.Ignore())
                .ForMember(dest => dest.Category, opt => opt.Ignore())
                .ForMember(dest => dest.RevenueAccount, opt => opt.Ignore())
                .ForMember(dest => dest.CogsAccount, opt => opt.Ignore())
                .ForMember(dest => dest.ImagePath, opt => opt.Ignore())
                .ForMember(dest => dest.ThumbnailPath, opt => opt.Ignore());

            // CatalogItem -> UpdateCatalogItemDto (reverse mapping for Edit)
            CreateMap<CatalogItem, UpdateCatalogItemDto>();
        }

        /// <summary>
        /// Builds the full category path by walking up the hierarchy.
        /// Example: "Wheels > 18 inch"
        /// </summary>
        private string GetCategoryPath(CatalogCategory category)
        {
            var path = new List<string>();
            var current = category;

            // Walk up the hierarchy
            while (current != null)
            {
                path.Insert(0, current.Name);
                current = current.ParentCategory;
            }

            return string.Join(" > ", path);
        }
    }
}
