using AutoMapper;
using Lada.Framework.Data.Domains.Orders;
using Lada.Framework.DTO.Enums;
using Lada.Framework.Infrastructures.Helpers;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Business.Operations;
using Ladaer.BackEnd.Infrastructures.DTO.Items.DriverApp;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Orders;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders.Detail;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders.Shared;

namespace Ladaer.BackEnd.Infrastructures.DTO.Profiles
{
    public class OrdersMappingProfile : Profile
    {
        public OrdersMappingProfile()
        {
            // Order mappings
            CreateMap<OrderModel, Order>();
            CreateMap<Order, OrderModel>();
            CreateMap<Order, OrderItem>();
            CreateMap<Order, OpsOrderItem>();
            CreateMap<Order, OrderDetailModel>()
                .ForMember(dest => dest.Finance, opt => opt.MapFrom(src => src.OrderFin))
                .ForMember(dest => dest.Packages, opt => opt.MapFrom(src => src.Packages))
                .ForPath(dest => dest.General.Code, opt => opt.MapFrom(src => src.Code))
                .ForPath(dest => dest.General.CustomerId, opt => opt.MapFrom(src => src.CustomerId))
                .ForPath(dest => dest.General.CustomerName, opt => opt.MapFrom(src => src.CreatedByUserName != null ? string.IsNullOrEmpty(src.Customer.UserName) ? src.Customer.FullName : src.Customer.UserName : ""))
                .ForPath(dest => dest.General.Status, opt => opt.MapFrom(src => src.OrderOps != null ? src.OrderOps.Status : 0))
                .ForPath(dest => dest.General.PhysicalStatus, opt => opt.MapFrom(src => src.OrderOps != null ? src.OrderOps.PhysicalStatus : 0))
                .ForPath(dest => dest.General.PicUserName, opt => opt.MapFrom(src => src.OrderOps.PicUserName))
                .ForPath(dest => dest.General.CreatedTime, opt => opt.MapFrom(src => src.CreatedTime))
                .ForPath(dest => dest.General.UpdatedTime, opt => opt.MapFrom(src => src.UpdatedTime));

            // OrderAddress mappings
            CreateMap<OrderAddressModel, OrderAddress>()
                .ForMember(dest => dest.PhoneNumber2, opt => opt.MapFrom(src => string.IsNullOrEmpty(src.PhoneNumber2) ? "" : src.PhoneNumber2))
                .ForMember(dest => dest.Address2, opt => opt.MapFrom(src => string.IsNullOrEmpty(src.Address2) ? "" : src.Address2));
            CreateMap<OrderAddress, OrderAddressModel>();
            CreateMap<OrderAddress, OrderAddressItem>();
            CreateMap<OrderAddress, OrderDetailAddressModel>();
            CreateMap<OrderAddress, UpdateOrderAddressModel>();

            // OrderPackage mappings
            CreateMap<OrderPackageModel, OrderPackage>();
            CreateMap<OrderPackage, OrderPackageModel>()
                .ForMember(dest => dest.Weight, opt => opt.MapFrom(src => UnitConverter.ConvertWeightToKilogram(src.Weight)))
                .ForMember(dest => dest.SubTotalWeight, opt => opt.MapFrom(src => UnitConverter.ConvertWeightToKilogram(src.SubTotalWeight)))
                .ForMember(dest => dest.Length, opt => opt.MapFrom(src => UnitConverter.ConvertDimensionToCentimeter(src.Length)))
                .ForMember(dest => dest.Width, opt => opt.MapFrom(src => UnitConverter.ConvertDimensionToCentimeter(src.Width)))
                .ForMember(dest => dest.Height, opt => opt.MapFrom(src => UnitConverter.ConvertDimensionToCentimeter(src.Height)));
            CreateMap<OrderPackage, OrderPackageItem>();
            CreateMap<OrderPackage, OrderPackageResponseItem>()
                .ForMember(dest => dest.Weight, opt => opt.MapFrom(src => UnitConverter.ConvertWeightToKilogram(src.Weight)))
                .ForMember(dest => dest.SubTotalWeight, opt => opt.MapFrom(src => UnitConverter.ConvertWeightToKilogram(src.SubTotalWeight)))
                .ForMember(dest => dest.Length, opt => opt.MapFrom(src => UnitConverter.ConvertDimensionToCentimeter(src.Length)))
                .ForMember(dest => dest.Width, opt => opt.MapFrom(src => UnitConverter.ConvertDimensionToCentimeter(src.Width)))
                .ForMember(dest => dest.Height, opt => opt.MapFrom(src => UnitConverter.ConvertDimensionToCentimeter(src.Height)))
                .ForMember(dest => dest.WeightUnit, opt => opt.MapFrom(src => UnitOfWeight.Kilogram))
                .ForMember(dest => dest.DimensionUnit, opt => opt.MapFrom(src => UnitOfDistance.Centimet));
            CreateMap<OrderPackage, OrderDetailPackageModel>()
                .ForMember(dest => dest.Weight, opt => opt.MapFrom(src => UnitConverter.ConvertWeightToKilogram(src.Weight)))
                .ForMember(dest => dest.SubTotalWeight, opt => opt.MapFrom(src => UnitConverter.ConvertWeightToKilogram(src.SubTotalWeight)))
                .ForMember(dest => dest.Length, opt => opt.MapFrom(src => UnitConverter.ConvertDimensionToCentimeter(src.Length)))
                .ForMember(dest => dest.Width, opt => opt.MapFrom(src => UnitConverter.ConvertDimensionToCentimeter(src.Width)))
                .ForMember(dest => dest.Height, opt => opt.MapFrom(src => UnitConverter.ConvertDimensionToCentimeter(src.Height)));

            // OrderFin mappings
            CreateMap<OrderFinModel, OrderFin>();
            CreateMap<OrderFin, OrderFinItem>()
                .ForMember(dest => dest.SourceFeeStage, opt => opt.MapFrom(src => src.SourceFeeStage.GetDescription()))
                .ForMember(dest => dest.DestFeeStage, opt => opt.MapFrom(src => src.DestFeeStage.GetDescription()))
                .ForMember(dest => dest.ReconciliationAmount, opt => opt.MapFrom(src => src.ReconciliationAmount));
            CreateMap<OrderFin, OrderDetailFinModel>()
                .ForMember(dest => dest.ReconciliationAmount, opt => opt.MapFrom(src => src.ReconciliationAmount));
            CreateMap<OrderFin, UpdateOrderFinModel>();

            // OrderOps mappings
            CreateMap<OrderOpsModel, OrderOps>();
            CreateMap<OrderOps, OrderOpsItem>();
            CreateMap<OrderOps, OpsOrderItem>()
                .ForMember(dest => dest.Code, opt => opt.MapFrom(src => src.Order != null ? src.Order.Code : ""))
                .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
                .ForMember(dest => dest.Note, opt => opt.MapFrom(src => src.Order != null ? src.Order.Note : ""))
                .ForMember(dest => dest.SaleId, opt => opt.MapFrom(src => src.Order != null ? src.Order.SaleId : 0))
                .ForMember(dest => dest.OrderFin, opt => opt.MapFrom(src => src.Order != null ? src.Order.OrderFin.ToItem() : new OrderFinItem()))
                .ForMember(dest => dest.Addresses, opt => opt.MapFrom(src => src.Order != null ? src.Order.Addresses != null && src.Order.Addresses.Any() ? src.Order.Addresses.Select(oa => oa.ToItem()).ToList() : new List<OrderAddressItem>() : new List<OrderAddressItem>()))
                .ForMember(dest => dest.Packages, opt => opt.MapFrom(src => src.Order != null ? src.Order.Packages != null && src.Order.Packages.Any() ? src.Order.Packages.Select(oa => oa.ToItem()).ToList() : new List<OrderPackageItem>() : new List<OrderPackageItem>()))
                .ForPath(dest => dest.OrderOps.OrderDirection, opt => opt.MapFrom(src => src.OrderDirection))
                .ForPath(dest => dest.OrderOps.Status, opt => opt.MapFrom(src => src.Status))
                .ForPath(dest => dest.OrderOps.PhysicalStatus, opt => opt.MapFrom(src => src.PhysicalStatus))
                .ForPath(dest => dest.OrderOps.StatusContent, opt => opt.MapFrom(src => src.StatusContent))
                .ForPath(dest => dest.OrderOps.PicId, opt => opt.MapFrom(src => src.PicId))
                .ForPath(dest => dest.OrderOps.PicUserName, opt => opt.MapFrom(src => src.PicUserName))
                .ForPath(dest => dest.OrderOps.PickupNote, opt => opt.MapFrom(src => src.PickupNote))
                .ForPath(dest => dest.OrderOps.DeliveryNote, opt => opt.MapFrom(src => src.DeliveryNote))
                .ForPath(dest => dest.OrderOps.DisplayOrder, opt => opt.MapFrom(src => src.DisplayOrder))
                .ForMember(dest => dest.PickupTime, opt => opt.MapFrom(src => src.Order != null && src.Order.OrderTimeTrack != null ? src.Order.OrderTimeTrack.PickupTime : null))
                .ForMember(dest => dest.DeliveryDate, opt => opt.MapFrom(src => src.Order != null && src.Order.OrderTimeTrack != null ? src.Order.OrderTimeTrack.DeliveryDate : null));

            // OrderOps to DriverOrderHistoryItem mapping
            CreateMap<OrderOps, DriverOrderHistoryItem>()
                .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
                .ForMember(dest => dest.Code, opt => opt.MapFrom(src => src.Order != null ? src.Order.Code : ""))
                .ForMember(dest => dest.PickedupByUserName, opt => opt.MapFrom(src => src.PickedupByUserName))
                .ForMember(dest => dest.PickedupByFullName, opt => opt.Ignore())
                .ForMember(dest => dest.DeliveredByUserName, opt => opt.MapFrom(src => src.DeliveredByUserName))
                .ForMember(dest => dest.DeliveredByFullName, opt => opt.Ignore())
                .ForMember(dest => dest.SenderName, opt => opt.Ignore())
                .ForMember(dest => dest.SenderPhone, opt => opt.Ignore())
                .ForMember(dest => dest.SenderAddress, opt => opt.Ignore())
                .ForMember(dest => dest.ReceiverName, opt => opt.Ignore())
                .ForMember(dest => dest.ReceiverPhone, opt => opt.Ignore())
                .ForMember(dest => dest.ReceiverAddress, opt => opt.Ignore())
                .ForMember(dest => dest.Addresses, opt => opt.MapFrom(src => src.Order != null && src.Order.Addresses != null ? src.Order.Addresses.Select(a => a.ToItem()).ToList() : new System.Collections.Generic.List<OrderAddressItem>()))
                .ForMember(dest => dest.Packages, opt => opt.MapFrom(src => src.Order != null && src.Order.Packages != null ? src.Order.Packages.Select(p => p.ToItem()).ToList() : new System.Collections.Generic.List<OrderPackageItem>()))
                .ForMember(dest => dest.PackageContent, opt => opt.Ignore())
                .ForMember(dest => dest.TotalPackages, opt => opt.Ignore())
                .ForMember(dest => dest.TotalWeight, opt => opt.MapFrom(src => src.Order != null && src.Order.OrderFin != null ? src.Order.OrderFin.ChargeWeight : 0))
                .ForMember(dest => dest.TotalFee, opt => opt.MapFrom(src => src.Order != null && src.Order.OrderFin != null ? src.Order.OrderFin.TotalFee : 0))
                .ForMember(dest => dest.CollectAmount, opt => opt.MapFrom(src => src.Order != null && src.Order.OrderFin != null ? src.Order.OrderFin.CollectAmount : 0))
                .ForMember(dest => dest.PayFeeType, opt => opt.MapFrom(src => src.Order != null && src.Order.OrderFin != null ? src.Order.OrderFin.PayFeeType : 0))
                .ForMember(dest => dest.PickupTime, opt => opt.MapFrom(src => src.Order != null && src.Order.OrderTimeTrack != null ? src.Order.OrderTimeTrack.PickupTime : null))
                .ForMember(dest => dest.DeliveryDate, opt => opt.MapFrom(src => src.Order != null && src.Order.OrderTimeTrack != null ? src.Order.OrderTimeTrack.DeliveryDate : null))
                .ForMember(dest => dest.OrderStatus, opt => opt.MapFrom(src => src.Status))
                .ForMember(dest => dest.OrderPhysicalStatus, opt => opt.MapFrom(src => src.PhysicalStatus))
                .ForMember(dest => dest.MediaUrls, opt => opt.Ignore());

            // OrderTrack mappings
            CreateMap<OrderTrack, OrderTrackItem>();
            CreateMap<OrderTrack, OrderDetailTrackModel>();
            CreateMap<OrderTrackModel, OrderTrack>()
                .ForMember(dest => dest.DataAfter, opt => opt.MapFrom(src => string.IsNullOrEmpty(src.DataAfter) ? "" : src.DataAfter))
                .ForMember(dest => dest.DataBefore, opt => opt.MapFrom(src => string.IsNullOrEmpty(src.DataBefore) ? "" : src.DataBefore));

            // Order to BasicOrderExportItem mapping
            CreateMap<Order, BasicOrderExportItem>()
                // Thông tin cơ bản
                .ForMember(dest => dest.OrderId, opt => opt.MapFrom(src => src.Id))
                .ForMember(dest => dest.OrderCode, opt => opt.MapFrom(src => src.Code))
                .ForMember(dest => dest.PartnerCode, opt => opt.MapFrom(src => src.PartnerCode))
                .ForMember(dest => dest.CustomerName, opt => opt.MapFrom(src => src.Customer != null ? src.Customer.FullName : ""))
                .ForMember(dest => dest.SaleName, opt => opt.Ignore()) // Sẽ được set trong service

                // Thông tin địa chỉ - sẽ được set trong service
                .ForMember(dest => dest.SenderName, opt => opt.Ignore())
                .ForMember(dest => dest.SenderAddress, opt => opt.Ignore())
                .ForMember(dest => dest.SenderPhone, opt => opt.Ignore())
                .ForMember(dest => dest.ReceiverName, opt => opt.Ignore())
                .ForMember(dest => dest.ReceiverAddress, opt => opt.Ignore())
                .ForMember(dest => dest.ReceiverPhone, opt => opt.Ignore())

                // Thông tin trạng thái
                .ForMember(dest => dest.OrderStatus, opt => opt.MapFrom(src => src.OrderOps != null ? src.OrderOps.Status.GetDescription() : ""))
                .ForMember(dest => dest.OrderPhysicalStatus, opt => opt.MapFrom(src => src.OrderOps != null ? src.OrderOps.PhysicalStatus.GetDescription() : ""))

                // Thông tin cước phí cơ bản
                .ForMember(dest => dest.ChargeWeight, opt => opt.MapFrom(src => src.OrderFin != null ? src.OrderFin.ChargeWeight : 0))
                .ForMember(dest => dest.TotalFee, opt => opt.MapFrom(src => src.OrderFin != null ? src.OrderFin.TotalFee : 0))
                .ForMember(dest => dest.CollectAmount, opt => opt.MapFrom(src => src.OrderFin != null ? src.OrderFin.CollectAmount : 0))
                .ForMember(dest => dest.PayFeeType, opt => opt.MapFrom(src => src.OrderFin != null ? src.OrderFin.PayFeeType.GetDescription() : ""))

                // Thông tin thời gian
                .ForMember(dest => dest.OrderCreatedTime, opt => opt.MapFrom(src => src.CreatedTime))
                .ForMember(dest => dest.PickupTime, opt => opt.MapFrom(src => src.OrderTimeTrack != null ? src.OrderTimeTrack.PickupTime : null))
                .ForMember(dest => dest.DeliveryTime, opt => opt.MapFrom(src => src.OrderTimeTrack != null ? src.OrderTimeTrack.DeliveryDate : null))

                // Thông tin hàng hóa - sẽ được set trong service
                .ForMember(dest => dest.TotalPackages, opt => opt.Ignore())
                .ForMember(dest => dest.TotalWeight, opt => opt.Ignore())
                .ForMember(dest => dest.PackageContent, opt => opt.Ignore())

                // Thông tin bổ sung
                .ForMember(dest => dest.Note, opt => opt.MapFrom(src => src.Note))

                // Các field kế thừa từ BaseItem
                .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
                .ForMember(dest => dest.CreatedBy, opt => opt.MapFrom(src => src.CreatedBy))
                .ForMember(dest => dest.CreatedByUserName, opt => opt.MapFrom(src => src.CreatedByUserName))
                .ForMember(dest => dest.CreatedTime, opt => opt.MapFrom(src => src.CreatedTime))
                .ForMember(dest => dest.UpdatedBy, opt => opt.MapFrom(src => src.UpdatedBy))
                .ForMember(dest => dest.UpdatedByUserName, opt => opt.MapFrom(src => src.UpdatedByUserName))
                .ForMember(dest => dest.UpdatedTime, opt => opt.MapFrom(src => src.UpdatedTime));
        }
    }

    public static class OrdersMappingExtensions
    {
        // Order extensions
        public static OrderModel ToModel(this Order entity)
            => entity.MapTo<Order, OrderModel>();

        public static Order ToEntity(this OrderModel entity)
            => entity.MapTo<OrderModel, Order>();

        public static OrderItem ToItem(this Order entity)
            => entity.MapTo<Order, OrderItem>();

        public static OpsOrderItem ToOpsItem(this Order entity)
            => entity.MapTo<Order, OpsOrderItem>();

        public static OrderDetailModel ToDetailModel(this Order entity)
            => entity.MapTo<Order, OrderDetailModel>();

        // OrderAddress extensions
        public static OrderAddress ToEntity(this OrderAddressModel entity)
            => entity.MapTo<OrderAddressModel, OrderAddress>();

        public static OrderAddressModel ToModel(this OrderAddress entity)
            => entity.MapTo<OrderAddress, OrderAddressModel>();

        public static UpdateOrderAddressModel ToUpdateModel(this OrderAddress entity)
            => entity.MapTo<OrderAddress, UpdateOrderAddressModel>();

        public static OrderAddressItem ToItem(this OrderAddress entity)
            => entity.MapTo<OrderAddress, OrderAddressItem>();

        public static List<OrderAddressItem> ToItem(this List<OrderAddress> entity)
            => entity.MapTo<List<OrderAddress>, List<OrderAddressItem>>();

        // OrderPackage extensions
        public static OrderPackage ToEntity(this OrderPackageModel entity)
            => entity.MapTo<OrderPackageModel, OrderPackage>();

        public static OrderPackageModel ToModel(this OrderPackage entity)
            => entity.MapTo<OrderPackage, OrderPackageModel>();

        public static OrderPackageItem ToItem(this OrderPackage entity)
            => entity.MapTo<OrderPackage, OrderPackageItem>();

        public static OrderPackageResponseItem ToResponseItem(this OrderPackage entity)
            => entity.MapTo<OrderPackage, OrderPackageResponseItem>();

        public static List<OrderPackageItem> ToItem(this List<OrderPackage> entity)
            => entity.MapTo<List<OrderPackage>, List<OrderPackageItem>>();

        public static List<OrderPackageResponseItem> ToResponseItem(this List<OrderPackage> entity)
            => entity.MapTo<List<OrderPackage>, List<OrderPackageResponseItem>>();

        // OrderFin extensions
        public static OrderFin ToEntity(this OrderFinModel entity)
            => entity.MapTo<OrderFinModel, OrderFin>();

        public static OrderFinItem ToItem(this OrderFin entity)
            => entity.MapTo<OrderFin, OrderFinItem>();

        public static UpdateOrderFinModel ToUpdateModel(this OrderFin entity)
            => entity.MapTo<OrderFin, UpdateOrderFinModel>();

        // OrderOps extensions
        public static OrderOps ToEntity(this OrderOpsModel entity)
            => entity.MapTo<OrderOpsModel, OrderOps>();

        public static OrderOpsItem ToItem(this OrderOps entity)
            => entity.MapTo<OrderOps, OrderOpsItem>();

        public static OpsOrderItem ToOpsOrderItem(this OrderOps entity)
            => entity.MapTo<OrderOps, OpsOrderItem>();

        public static DriverOrderHistoryItem ToDriverOrderHistoryItem(this OrderOps entity)
            => entity.MapTo<OrderOps, DriverOrderHistoryItem>();

        // OrderTrack extensions
        public static OrderTrack ToEntity(this OrderTrackModel entity)
            => entity.MapTo<OrderTrackModel, OrderTrack>();

        public static OrderTrackItem ToItem(this OrderTrack entity)
            => entity.MapTo<OrderTrack, OrderTrackItem>();

        public static List<OrderTrackItem> ToItem(this List<OrderTrack> entity)
            => entity.MapTo<List<OrderTrack>, List<OrderTrackItem>>();

        // OrderTimeTrack extensions
        public static OrderTimeTrack ToEntity(this OrderTimeTrackModel entity)
            => entity.MapTo<OrderTimeTrackModel, OrderTimeTrack>();
    }
}