using AutoMapper;
using Lada.Framework.Data.Domains.Categories;
using Lada.Framework.Data.Domains.Cms;
using Lada.Framework.Data.Domains.Crm;
using Lada.Framework.Data.Domains.ErrorReports;
using Lada.Framework.Data.Domains.Finance;
using Lada.Framework.Data.Domains.Finance.Quotations;
using Lada.Framework.Data.Domains.Finance.Wallets;
using Lada.Framework.Data.Domains.Hr;
using Lada.Framework.Data.Domains.Identity;
using Lada.Framework.Data.Domains.Orders;
using Lada.Framework.Data.Domains.Settings;
using Lada.Framework.Data.Domains.Trucks;
using Lada.Framework.DTO.Enums;
using Lada.Framework.Infrastructures.Helpers;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Business.Operations;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Categories;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Cms;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Crm;
using Ladaer.BackEnd.Infrastructures.DTO.Items.ErrorReports;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Finances;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Hr;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Identity;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Orders;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Settings;
using Ladaer.BackEnd.Infrastructures.DTO.Items.Trucks;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Categories;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Cms;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Crm;
using Ladaer.BackEnd.Infrastructures.DTO.Models.ErrorReports;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Finances;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Hr;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Itentity;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders.Detail;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Orders.Shared;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Settings;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Trucks;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Users;
using Ladaer.BackEnd.Infrastructures.DTO.Profiles;
using Route = Lada.Framework.Data.Domains.Finance.Quotations.Route;

namespace Ladaer.BackEnd.Infrastructures.DTO
{
    public class AutoMapperConfig
    {
        #region Properties
        private static MapperConfiguration _mapperConfiguration;
        private static IMapper _mapper;

        /// <summary>
        /// Mapper
        /// </summary>
        public static IMapper Mapper => _mapper;

        /// <summary>
        /// Mapper configuration
        /// </summary>
        public static MapperConfiguration MapperConfiguration => _mapperConfiguration;
        #endregion

        /// <summary>
        /// Init
        /// </summary>
        public static void Init()
        {
            try
            {
                _mapperConfiguration = new MapperConfiguration(cfg =>
                {
                    cfg.AddProfile<FinanceMappingProfile>();
                    cfg.AddProfile<IdentityMappingProfile>();
                    cfg.AddProfile<CrmMappingProfile>();
                    cfg.AddProfile<OrdersMappingProfile>();
                    cfg.AddProfile<CmsMappingProfile>();
                    cfg.AddProfile<CategoriesMappingProfile>();
                    cfg.AddProfile<HrMappingProfile>();
                    cfg.AddProfile<AppConfigMappingProfile>();
                    cfg.AddProfile<TruckMappingProfile>();
                    cfg.AddProfile<PremiseMappingProfile>();
                    cfg.AddProfile<OrderBusinessMappingProfile>();
                    cfg.AddProfile<RewardPenaltyMappingProfile>();
                    // Đã tách HR ra profile riêng

                    #region Price
                    //PriceDetailModel
                    cfg.CreateMap<Price, PriceDetailModel>();
                    #endregion

                    #region Wallet

                    cfg.CreateMap<Wallet, WalletItem>()
                        .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => src.User != null ? src.User.FullName : ""))
                        .ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.User != null ? src.User.UserName : ""))
                        .ForMember(dest => dest.WalletStatus, opt => opt.MapFrom(src => src.WalletStatus.GetDescription()))
                        .ForMember(dest => dest.Balance, opt => opt.MapFrom(src => src.Balance.FormatCurrency()))
                        .ForMember(dest => dest.WalletType, opt => opt.MapFrom(src => src.WalletType.GetDescription()))
                        .ForMember(dest => dest.CreatedByUserName, opt => opt.MapFrom(src => src.CreatedByUserName))
                        .ForMember(dest => dest.UpdatedByUserName, opt => opt.MapFrom(src => src.UpdatedByUserName));
                    cfg.CreateMap<Wallet, WalletDetailModel>()
                        .ForMember(dest => dest.WalletStatus, opt => opt.MapFrom(src => src.WalletStatus.GetDescription()))
                        .ForMember(dest => dest.UserId, opt => opt.MapFrom(src => src.User != null ? src.User.Id : 0))
                        .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => src.User != null ? src.User.FullName : ""))
                        .ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.User != null ? src.User.UserName : ""));

                    cfg.CreateMap<Transaction, TransactionItem>()
                        .ForMember(dest => dest.CreatedByUserName, opt => opt.MapFrom(src => src.CreatedByUserName))
                        .ForMember(dest => dest.TransactionType, opt => opt.MapFrom(src => src.TransactionType.GetDescription()))
                        .ForMember(dest => dest.UpdatedByUserName, opt => opt.MapFrom(src => src.UpdatedByUserName));
                    #endregion


                    #region Truck
                    // NOTE: Truck mappings are now in TruckMappingProfile
                    // Keeping these for backward compatibility until fully migrated
                    cfg.CreateMap<TruckModel, Truck>();
                    cfg.CreateMap<Truck, TruckModel>();
                    cfg.CreateMap<Truck, TruckItem>();

                    cfg.CreateMap<TruckActivityModel, TruckActivity>();
                    cfg.CreateMap<TruckActivity, TruckActivityItem>();

                    cfg.CreateMap<TruckAssetModel, TruckAsset>();
                    cfg.CreateMap<TruckAsset, TruckAssetItem>();

                    cfg.CreateMap<TruckSpecAttributeModel, TruckSpecAttribute>();
                    cfg.CreateMap<TruckSpecAttribute, TruckSpecAttributeItem>();

                    cfg.CreateMap<TruckMaintAttributeModel, TruckMaintAttribute>();
                    cfg.CreateMap<TruckMaintAttribute, TruckMaintAttributeItem>();

                    cfg.CreateMap<TruckMaintLinkModel, TruckMaintLink>();
                    cfg.CreateMap<TruckMaintLink, TruckMaintLinkItem>();

                    cfg.CreateMap<TruckMaintenanceModel, TruckMaintenance>();
                    cfg.CreateMap<TruckMaintenance, TruckMaintenanceItem>();

                    cfg.CreateMap<TruckSpecificationModel, TruckSpecification>();
                    cfg.CreateMap<TruckSpecification, TruckSpecificationItem>();
                    #endregion

                    // Đã tách CMS mappings sang CmsMappingProfile.cs

                    #region ScriptConfig
                    cfg.CreateMap<ScriptConfig, ScriptConfigModel>().ReverseMap();
                    cfg.CreateMap<ScriptConfig, ScriptConfigItem>();
                    cfg.CreateMap<ScriptConfigModel, ScriptConfigItem>();
                    #endregion

                    #region ErrorReport
                    cfg.CreateMap<ErrorReport, ErrorReportItem>()
                        .ForMember(dest => dest.StatusDisplay, opt => opt.MapFrom(src => src.Status.GetDescription()))
                        .ForMember(dest => dest.MediaItems, opt => opt.MapFrom(src => src.ErrorReportMedias));

                    cfg.CreateMap<ErrorReportModel, ErrorReport>()
                        .ForMember(dest => dest.Id, opt => opt.Ignore())
                        .ForMember(dest => dest.Status, opt => opt.Ignore())
                        .ForMember(dest => dest.AdminNote, opt => opt.Ignore())
                        .ForMember(dest => dest.ReportedByUserId, opt => opt.Ignore())
                        .ForMember(dest => dest.ErrorReportMedias, opt => opt.Ignore())
                        .ForMember(dest => dest.CreatedTime, opt => opt.Ignore())
                        .ForMember(dest => dest.UpdatedTime, opt => opt.Ignore())
                        .ForMember(dest => dest.CreatedBy, opt => opt.Ignore())
                        .ForMember(dest => dest.CreatedByUserName, opt => opt.Ignore())
                        .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore())
                        .ForMember(dest => dest.UpdatedByUserName, opt => opt.Ignore())
                        .ForMember(dest => dest.IsDeleted, opt => opt.Ignore());

                    cfg.CreateMap<ErrorReportMedia, ErrorReportMediaItem>()
                        .ForMember(dest => dest.ImageUrl, opt => opt.Ignore()) // Sẽ được set trong service
                        .ForMember(dest => dest.FileSizeDisplay, opt => opt.Ignore()); // Sẽ được set trong service
                    #endregion

                    #region CallPath
                    cfg.AddProfile<CallPathMappingProfile>();
                    #endregion

                    #region Bank Management
                    cfg.CreateMap<BankAccount, BankAccountItem>()
                        .ForMember(dest => dest.BankName, opt => opt.MapFrom(src => src.Bank != null ? $"{src.Bank.BrandName} ({src.Bank.FullName})" : ""))
                        .ForMember(dest => dest.ManagerUserName, opt => opt.MapFrom(src => src.ManagerUser != null ? src.ManagerUser.UserName : ""))
                        .ForMember(dest => dest.ManagerFullName, opt => opt.MapFrom(src => src.ManagerUser != null ? src.ManagerUser.FullName : ""))
                        .ForMember(dest => dest.TransactionCount, opt => opt.MapFrom(src => src.BankTransactions != null ? src.BankTransactions.Count : 0));

                    cfg.CreateMap<BankAccountModel, BankAccount>()
                        .ForMember(dest => dest.Id, opt => opt.Condition(src => src.Id > 0))
                        .ForMember(dest => dest.BankTransactions, opt => opt.Ignore())
                        .ForMember(dest => dest.BankStatementImports, opt => opt.Ignore())
                        .ForMember(dest => dest.ManagerUser, opt => opt.Ignore())
                        .ForMember(dest => dest.LastBalanceUpdate, opt => opt.Ignore())
                        .ForMember(dest => dest.LastTransactionDate, opt => opt.Ignore());

                    cfg.CreateMap<BankTransaction, BankTransactionItem>()
                        .ForMember(dest => dest.CreditAmount, opt => opt.MapFrom(src => src.CreditAmount > 0 ? src.CreditAmount.ToString("N0") : ""))
                        .ForMember(dest => dest.DebitAmount, opt => opt.MapFrom(src => src.DebitAmount > 0 ? src.DebitAmount.ToString("N0") : ""))
                        .ForMember(dest => dest.Balance, opt => opt.MapFrom(src => src.Balance.ToString("N0")))
                        .ForMember(dest => dest.ProcessStatus, opt => opt.MapFrom(src => src.ProcessStatus.GetDescription()))
                        .ForMember(dest => dest.TransactionType, opt => opt.MapFrom(src => src.TransactionType != null ? src.TransactionType.GetDescription() : ""))
                        .ForMember(dest => dest.BankAccountName, opt => opt.MapFrom(src => src.BankAccount != null ? src.BankAccount.AccountName : ""))
                        .ForMember(dest => dest.BankAccountNumber, opt => opt.MapFrom(src => src.BankAccount != null ? src.BankAccount.AccountNumber : ""));

                    cfg.CreateMap<BankStatementImport, BankStatementImportItem>()
                        .ForMember(dest => dest.ImportStatus, opt => opt.MapFrom(src => src.ImportStatus.GetDescription()))
                        .ForMember(dest => dest.BankAccountName, opt => opt.MapFrom(src => src.BankAccount != null ? src.BankAccount.AccountName : ""))
                        .ForMember(dest => dest.BankAccountNumber, opt => opt.MapFrom(src => src.BankAccount != null ? src.BankAccount.AccountNumber : ""))
                        .ForMember(dest => dest.FileSize, opt => opt.Ignore()) // Will be formatted in extension method
                        .ForMember(dest => dest.ProcessDuration, opt => opt.Ignore()) // Will be calculated in extension method
                        .ForMember(dest => dest.SuccessRate, opt => opt.Ignore()); // Will be calculated in extension method

                    #endregion


                });

                _mapper = _mapperConfiguration.CreateMapper();
            }
            catch (System.Exception)
            {

                throw;
            }

        }
    }
}