using Grand.Business.Core.Utilities.Catalog;
using Grand.Domain.Catalog;
using Grand.Domain.Orders;
using Grand.Infrastructure.ModelBinding;
using Grand.Infrastructure.Models;
using Grand.Web.Models.Media;
using Microsoft.AspNetCore.Mvc.Rendering;

namespace Grand.Web.Models.Catalog
{
    public class ProductDetailsModel : BaseEntityModel
    {
        //picture(s)
        public bool DefaultPictureZoomEnabled { get; set; }
        public PictureModel DefaultPictureModel { get; set; } = new();
        public IList<PictureModel> PictureModels { get; set; } = new List<PictureModel>();
        public ProductType ProductType { get; set; }
        public string Name { get; set; }
        public string ShortDescription { get; set; }
        public string FullDescription { get; set; }
        public string MetaKeywords { get; set; }
        public string MetaDescription { get; set; }
        public string MetaTitle { get; set; }
        public string SeName { get; set; }
        public bool ShowSku { get; set; }
        public string Sku { get; set; }
        public string Flag { get; set; }
        public bool ShowMpn { get; set; }
        public string Mpn { get; set; }
        public bool ShowGtin { get; set; }
        public string Gtin { get; set; }
        public BrandBriefInfoModel BrandModel { get; set; } = new();
        public bool ShowVendor { get; set; }
        public VendorBriefInfoModel VendorModel { get; set; } = new();
        public bool HasSampleDownload { get; set; }
        public GiftVoucherModel GiftVoucher { get; set; } = new();
        public bool IsShipEnabled { get; set; }
        public bool NotReturnable { get; set; }
        public bool IsFreeShipping { get; set; }
        public bool AllowToSelectWarehouse { get; set; }
        public IList<ProductWarehouseModel> ProductWarehouses { get; set; } = new List<ProductWarehouseModel>();
        public double AdditionalShippingCharge { get; set; }
        public string AdditionalShippingChargeStr { get; set; }
        public bool FreeShippingNotificationEnabled { get; set; }
        public string DeliveryDate { get; set; }
        public string DeliveryColorSquaresRgb { get; set; }
        public int Interval { get; set; }
        public IntervalUnit IntervalUnit { get; set; }
        public bool IncBothDate { get; set; }
        public List<SelectListItem> Parameters { get; set; } = new();
        public DateTime StartDate { get; set; }
        public DateTime? RentalStartDateUtc { get; set; }
        public DateTime? RentalEndDateUtc { get; set; }
        public string RentalReservationId { get; set; }
        public string StockAvailability { get; set; }
        public bool DisplayOutOfStockSubscription { get; set; }
        public bool EmailAFriendEnabled { get; set; }
        public bool AskQuestionOnProduct { get; set; }
        public ProductAskQuestionSimpleModel ProductAskQuestion { get; set; }
        public bool CompareProductsEnabled { get; set; }
        public string PageShareCode { get; set; }
        public ProductPriceModel ProductPrice { get; set; } = new();
        public AddToCartModel AddToCart { get; set; } = new();
        public ProductBreadcrumbModel Breadcrumb { get; set; } = new();
        public IList<ProductTagModel> ProductTags { get; set; } = new List<ProductTagModel>();
        public IList<ProductAttributeModel> ProductAttributes { get; set; } = new List<ProductAttributeModel>();
        public IList<ProductSpecificationModel> ProductSpecifications { get; set; } = new List<ProductSpecificationModel>();
        public IList<CollectionModel> ProductCollections { get; set; } = new List<CollectionModel>();
        public ProductReviewOverviewModel ProductReviewOverview { get; set; } = new();

        public IList<TierPriceModel> TierPrices { get; set; } = new List<TierPriceModel>();

        //a list of associated products. For example, "Grouped" products could have several child "simple" products
        public IList<ProductDetailsModel> AssociatedProducts { get; set; } = new List<ProductDetailsModel>();

        //bundle product 
        public IList<ProductBundleModel> ProductBundleModels { get; set; } = new List<ProductBundleModel>();
        public bool DisplayDiscontinuedMessage { get; set; }
        public string CurrentStoreName { get; set; }
        public double StartPrice { get; set; }
        public double HighestBidValue { get; set; }
        public DateTime? EndTime { get; set; }
        public DateTime? EndTimeLocalTime { get; set; }
        public bool AuctionEnded { get; set; }
        public bool RenderCaptcha { get; set; }

        #region Nested Classes
        public class ProductBreadcrumbModel : BaseModel
        {
            public int Id { get; set; }
            public bool Enabled { get; set; }
            public string ProductId { get; set; }
            public string ProductName { get; set; }
            public string ProductSeName { get; set; }
            public IList<CategorySimpleModel> CategoryBreadcrumb { get; set; } = new List<CategorySimpleModel>();
        }

        public class AddToCartModel : BaseModel
        {
            public string ProductId { get; set; }
            //qty
            [GrandResourceDisplayName("Products.Qty")]
            public int EnteredQuantity { get; set; }
            public string MinimumQuantityNotification { get; set; }
            public List<SelectListItem> AllowedQuantities { get; set; } = new();

            //price entered by customers
            [GrandResourceDisplayName("Products.EnterProductPrice")]
            public bool EnteredPrice { get; set; }
            [GrandResourceDisplayName("Products.EnterProductPrice")]
            public double CustomerEnteredPrice { get; set; }
            public string CustomerEnteredPriceRange { get; set; }
            public bool DisableBuyButton { get; set; }
            public bool DisableWishlistButton { get; set; }
            //reservation
            public bool IsReservation { get; set; }
            //auction
            public bool IsAuction { get; set; }
            public string MeasureUnit { get; set; }
            //pre-order
            public bool AvailableForPreOrder { get; set; }
            public DateTime? PreOrderDateTimeUtc { get; set; }
            //updating existing shopping cart or wishlist item?
            public string UpdatedShoppingCartItemId { get; set; }
            public ShoppingCartType? UpdateShoppingCartItemType { get; set; }
        }

        public class ProductPriceModel : BaseModel
        {
            /// <summary>
            /// The currency (in 3-letter ISO 4217 format) of the offer price 
            /// </summary>
            public string CurrencyCode { get; set; }
            public string OldPrice { get; set; }
            public string CatalogPrice { get; set; }
            public string Price { get; set; }
            public string PriceWithDiscount { get; set; }
            public double PriceValue { get; set; }
            public bool EnteredPrice { get; set; }
            public bool CallForPrice { get; set; }
            public string ProductId { get; set; }
            public bool HidePrices { get; set; }
            //Reservation
            public bool IsReservation { get; set; }
            public string ReservationPrice { get; set; }
            //Auction
            public bool IsAuction { get; set; }
            public string HighestBid { get; set; }
            public double HighestBidValue { get; set; }
            public string StartPrice { get; set; }
            public double StartPriceValue { get; set; }
            public bool DisableBuyButton { get; set; }

            public string BasePricePAngV { get; set; }

            public List<ApplyDiscount> AppliedDiscounts { get; set; } = new();
            public TierPrice PreferredTierPrice { get; set; }
        }

        public class GiftVoucherModel : BaseModel
        {
            public bool IsGiftVoucher { get; set; }

            [GrandResourceDisplayName("Products.GiftVoucher.RecipientName")]
            public string RecipientName { get; set; }
            [GrandResourceDisplayName("Products.GiftVoucher.RecipientEmail")]
            public string RecipientEmail { get; set; }
            [GrandResourceDisplayName("Products.GiftVoucher.SenderName")]
            public string SenderName { get; set; }
            [GrandResourceDisplayName("Products.GiftVoucher.SenderEmail")]
            public string SenderEmail { get; set; }
            [GrandResourceDisplayName("Products.GiftVoucher.Message")]
            public string Message { get; set; }

            public GiftVoucherType GiftVoucherType { get; set; }
        }

        public class TierPriceModel : BaseModel
        {
            public string Price { get; set; }

            public int Quantity { get; set; }
        }

        public class ProductAttributeModel : BaseEntityModel
        {
            public string ProductId { get; set; }
            public string ProductAttributeId { get; set; }
            public string Name { get; set; }
            public string Description { get; set; }
            public string TextPrompt { get; set; }
            public bool IsRequired { get; set; }
            /// <summary>
            /// Default value for textboxes
            /// </summary>
            public string DefaultValue { get; set; }
            /// <summary>
            /// Selected day value for datepicker
            /// </summary>
            public int? SelectedDay { get; set; }
            /// <summary>
            /// Selected month value for datepicker
            /// </summary>
            public int? SelectedMonth { get; set; }
            /// <summary>
            /// Selected year value for datepicker
            /// </summary>
            public int? SelectedYear { get; set; }

            /// <summary>
            /// A value indicating whether this attribute depends on some other attribute
            /// </summary>
            public bool HasCondition { get; set; }

            /// <summary>
            /// Allowed file extensions for customer uploaded files
            /// </summary>
            public IList<string> AllowedFileExtensions { get; set; } = new List<string>();

            public AttributeControlType AttributeControlType { get; set; }
            public IList<ProductAttributeValueModel> Values { get; set; } = new List<ProductAttributeValueModel>();
        }

        public class ProductAttributeValueModel : BaseEntityModel
        {
            public string Name { get; set; }
            public string ColorSquaresRgb { get; set; }
            //picture model is used with "image square" attribute type
            public PictureModel ImageSquaresPictureModel { get; set; } = new();
            public string PriceAdjustment { get; set; }
            public double PriceAdjustmentValue { get; set; }
            public string StockAvailability { get; set; }
            public bool IsPreSelected { get; set; }
            //picture model is used when we want to override a default product picture when some attribute is selected
            public PictureModel PictureModel { get; set; } = new();
        }

        public class ProductBundleModel : BaseModel
        {
            public string ProductId { get; set; }
            public string Name { get; set; }
            public string SeName { get; set; }
            public string ShortDescription { get; set; }
            public string Sku { get; set; }
            public string Mpn { get; set; }
            public string Gtin { get; set; }
            public int Quantity { get; set; }
            public string Price { get; set; }
            public double PriceValue { get; set; }
            public PictureModel DefaultPictureModel { get; set; }
            public IList<ProductAttributeModel> ProductAttributes { get; set; } = new List<ProductAttributeModel>();
        }

        public class ProductWarehouseModel : BaseModel
        {
            public bool Use { get; set; }
            public string WarehouseId { get; set; }
            public string Code { get; set; }
            public string Name { get; set; }
            public int StockQuantity { get; set; }
            public int ReservedQuantity { get; set; }
            public bool Selected { get; set; }
        }
        #endregion
    }
}