using RFrameGenerate.BLL.Products;
using RFrameGenerate.Common;
using RFrameGenerate.DAL.Interface;
using RFrameGenerate.Model;
using RFrameGenerate.Model.PageModel;
using RFramework.SQLServer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RFrameGenerate.BLL.Logistics
{
    public class TemplatesManage
    {
        #region 数据读取

        /// <summary>
        /// 获取模板
        /// </summary>        
        public static T_BAS_Templates GetEntity(Guid templatesGuid, Guid? merGuid = null)
        {
            if (templatesGuid == Guid.Empty) return null;

            using (var query = Factory.CreateT_BAS_Templates())
            {
                if (merGuid == null)
                {
                    merGuid = CurrentManage.MerchantGuid;
                }
                return query.GetFirstData(m => m.MerchantGuid == merGuid && m.TemplatesGuid == templatesGuid, isFilterMerchant: false);
            }
        }

        /// <summary>
        /// 是否存在模板
        /// </summary>   
        public static bool ExistsTemplate(Guid templatesGuid)
        {
            using (var query = Factory.CreateT_BAS_Templates())
            {
                return query.IsExist(m => m.MerchantGuid == CurrentManage.MerchantGuid && m.TemplatesGuid == templatesGuid);
            }
        }

        /// <summary>
        /// 分页读取数据
        /// </summary>
        public static List<T_BAS_Templates> GetPageList(GridModel gridModel)
        {
            using (var query = Factory.CreateT_BAS_Templates())
            {
                return query.GetPageList(gridModel, m => m.MerchantGuid == CurrentManage.MerchantGuid, false, v => v.Sort);
            }
        }


        public static List<T_BAS_Templates> GetList(Guid? merGuid = null)
        {
            using (var query = Factory.CreateT_BAS_Templates())
            {
                if (merGuid == null)
                {
                    merGuid = CurrentManage.MerchantGuid;
                }
                return query.GetList(m => m.MerchantGuid == merGuid, false, v => v.Sort, isFilterMerchant: false);
            }
        }
        #endregion

        #region 数据操作

        public static Result DeleteTemplates(Guid templatesGuid)
        {
            if (templatesGuid == Guid.Empty || !IsExists(templatesGuid)) return new Result(false, "删除模板不能为空！");

            if (IsUsingTemplate(templatesGuid)) return new Result(false, "已有商品使用该模板，不能删除！");

            SqlRTransaction trans = null;
            IQuery<T_BAS_Templates> queryTemplates = null;
            IQuery<T_BAS_ShippingMethod> queryShipping = null;
            IQuery<T_BAS_PackageMail> queryPack = null;

            try
            {
                trans = new SqlRTransaction();
                trans.BeginTransaction();

                queryTemplates = Factory.CreateT_BAS_Templates(trans);
                queryShipping = Factory.CreateT_BAS_ShippingMethod(trans);
                queryPack = Factory.CreateT_BAS_PackageMail(trans);

                queryTemplates.Delete(m => m.TemplatesGuid == templatesGuid);
                queryShipping.Delete(m => m.TemplatesGuid == templatesGuid);
                queryPack.Delete(m => m.TemplatesGuid == templatesGuid);

                trans.Commit();

                return new Result(true);
            }
            catch (Exception ex)
            {
                Wechat.LogManage.Log("Thread ID : " + System.Threading.Thread.CurrentThread.ManagedThreadId + " 删除模板失败！ Message :" + ex.Message);
                Wechat.LogManage.Log("Thread ID : " + System.Threading.Thread.CurrentThread.ManagedThreadId + " 删除模板失败！ Source :" + ex.Source);
                Wechat.LogManage.Log("Thread ID : " + System.Threading.Thread.CurrentThread.ManagedThreadId + " 删除模板失败！ StackTrace :" + ex.StackTrace);

                return new Result(false, ex.Message);
            }
            finally
            {
                if (queryTemplates != null) queryTemplates.Dispose();
                if (queryShipping != null) queryShipping.Dispose();
                if (queryPack != null) queryPack.Dispose();

                if (trans != null)
                {
                    trans.Dispose();

                    if (trans.SqlConnection != null && trans.SqlConnection.State != System.Data.ConnectionState.Closed)
                    {
                        trans.SqlConnection.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 保存模板
        /// </summary>
        public static Result SaveTemplates(T_BAS_Templates templates, List<T_BAS_ShippingMethod> list, List<T_BAS_PackageMail> packList)
        {
            var cbState = CheckTemplates(templates, list, packList);

            if (!cbState.State) return new Result(false, cbState.Msg);

            if (templates.TemplatesGuid == Guid.Empty) return AddTemplates(templates, list, packList);

            if (ExistsTemplate(templates.TemplatesGuid)) return UpdateTemplates(templates, list, packList);

            return AddTemplates(templates, list, packList);
        }

        /// <summary>
        /// 添加模板
        /// </summary>
        private static Result AddTemplates(T_BAS_Templates templates, List<T_BAS_ShippingMethod> list, List<T_BAS_PackageMail> packList)
        {
            SqlRTransaction trans = null;
            IQuery<T_BAS_Templates> queryTemplates = null;
            IQuery<T_BAS_ShippingMethod> queryShipping = null;
            IQuery<T_BAS_PackageMail> queryPack = null;

            templates.TemplatesGuid = Guid.NewGuid();
            templates.MerchantGuid = CurrentManage.MerchantGuid;

            foreach (var item in list)
            {
                item.ShippingMethodGuid = Guid.NewGuid();
                item.TemplatesGuid = templates.TemplatesGuid;
                item.EntityState = EntityStates.ToBeAdd;
            }
            if (templates.IsPinkage != 2 && templates.IsPackageMail != null && templates.IsPackageMail.Value)
            {
                foreach (var item in packList)
                {
                    item.PackageMailGuid = Guid.NewGuid();
                    item.TemplatesGuid = templates.TemplatesGuid;
                    item.EntityState = EntityStates.ToBeAdd;
                }
            }
            try
            {
                trans = new SqlRTransaction();
                trans.BeginTransaction();

                queryTemplates = Factory.CreateT_BAS_Templates(trans);
                queryShipping = Factory.CreateT_BAS_ShippingMethod(trans);

                queryTemplates.Add(templates);
                queryShipping.AddList(list);

                if (templates.IsPinkage != 2 && templates.IsPackageMail != null && templates.IsPackageMail.Value)
                {
                    queryPack = Factory.CreateT_BAS_PackageMail(trans);

                    queryPack.AddList(packList);
                }

                trans.Commit();

                return new Result(true);
            }
            catch (Exception ex)
            {
                Wechat.LogManage.Log("Thread ID : " + System.Threading.Thread.CurrentThread.ManagedThreadId + " 添加模板失败！ Message :" + ex.Message);
                Wechat.LogManage.Log("Thread ID : " + System.Threading.Thread.CurrentThread.ManagedThreadId + " 添加模板失败！ Source :" + ex.Source);
                Wechat.LogManage.Log("Thread ID : " + System.Threading.Thread.CurrentThread.ManagedThreadId + " 添加模板失败！ StackTrace :" + ex.StackTrace);

                return new Result(false, ex.Message);
            }
            finally
            {
                if (queryTemplates != null) queryTemplates.Dispose();
                if (queryShipping != null) queryShipping.Dispose();
                if (queryPack != null) queryPack.Dispose();

                if (trans != null)
                {
                    trans.Dispose();

                    if (trans.SqlConnection != null && trans.SqlConnection.State != System.Data.ConnectionState.Closed)
                    {
                        trans.SqlConnection.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 更新模板
        /// </summary>
        private static Result UpdateTemplates(T_BAS_Templates templates, List<T_BAS_ShippingMethod> list, List<T_BAS_PackageMail> packList)
        {
            SqlRTransaction trans = null;
            IQuery<T_BAS_Templates> queryTemplates = null;
            IQuery<T_BAS_ShippingMethod> queryShipping = null;
            IQuery<T_BAS_PackageMail> queryPack = null;

            templates.MerchantGuid = CurrentManage.MerchantGuid;

            foreach (var item in list)
            {
                item.ShippingMethodGuid = Guid.NewGuid();
                item.TemplatesGuid = templates.TemplatesGuid;
                item.EntityState = EntityStates.ToBeAdd;
            }
            if (templates.IsPinkage != 2 && templates.IsPackageMail != null && templates.IsPackageMail.Value)
            {
                foreach (var item in packList)
                {
                    item.PackageMailGuid = Guid.NewGuid();
                    item.TemplatesGuid = templates.TemplatesGuid;
                    item.EntityState = EntityStates.ToBeAdd;
                }
            }
            try
            {
                trans = new SqlRTransaction();
                trans.BeginTransaction();

                queryTemplates = Factory.CreateT_BAS_Templates(trans);
                queryShipping = Factory.CreateT_BAS_ShippingMethod(trans);

                queryTemplates.Update(m => new object[]{
                    m.TemplateName == templates.TemplateName,
                    m.MerchantGuid == templates.MerchantGuid,
                    m.Province == templates.Province,
                    m.City == templates.City,
                    m.Area == templates.Area,
                    m.DeliveryTime == templates.DeliveryTime,
                    m.IsPinkage == templates.IsPinkage,
                    m.Sort == templates.Sort,
                    m.ValuationWay == templates.ValuationWay,
                    m.IsPackageMail == templates.IsPackageMail,
                }, v => v.TemplatesGuid == templates.TemplatesGuid);

                queryShipping.Delete(m => m.TemplatesGuid == templates.TemplatesGuid);

                queryShipping.AddList(list);

                if (templates.IsPinkage != 2 && templates.IsPackageMail != null && templates.IsPackageMail.Value)
                {
                    queryPack = Factory.CreateT_BAS_PackageMail(trans);

                    queryPack.Delete(m => m.TemplatesGuid == templates.TemplatesGuid);
                    queryPack.AddList(packList);
                }

                trans.Commit();

                return new Result(true);
            }
            catch (Exception ex)
            {
                Wechat.LogManage.Log("Thread ID : " + System.Threading.Thread.CurrentThread.ManagedThreadId + " 添加模板失败！ Message :" + ex.Message);
                Wechat.LogManage.Log("Thread ID : " + System.Threading.Thread.CurrentThread.ManagedThreadId + " 添加模板失败！ Source :" + ex.Source);
                Wechat.LogManage.Log("Thread ID : " + System.Threading.Thread.CurrentThread.ManagedThreadId + " 添加模板失败！ StackTrace :" + ex.StackTrace);

                return new Result(false, ex.Message);
            }
            finally
            {
                if (queryTemplates != null) queryTemplates.Dispose();
                if (queryShipping != null) queryShipping.Dispose();
                if (queryPack != null) queryPack.Dispose();

                if (trans != null)
                {
                    trans.Dispose();

                    if (trans.SqlConnection != null && trans.SqlConnection.State != System.Data.ConnectionState.Closed)
                    {
                        trans.SqlConnection.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 检查错误
        /// </summary>        
        private static Result CheckTemplates(T_BAS_Templates templates, List<T_BAS_ShippingMethod> list, List<T_BAS_PackageMail> packList)
        {
            if (templates == null) return new Result(false, "模板内容不能为空！");

            if (list == null || list.Count <= 0) return new Result(false, "至少选择一种快递方式！");

            if (string.IsNullOrEmpty(templates.TemplateName)) return new Result(false, "用户模板不能为空！");

            if (templates.ValuationWay == null) return new Result(false, "计价方式不能为空！");

            if (templates.IsPinkage == null) return new Result(false, "包邮方式不能为空！");

            if (list.Count(m => string.IsNullOrEmpty(m.SupportArea) && m.ExType == 1) > 1) return new Result(false, "默认地址不能大于一个");

            if (list.Count(m => string.IsNullOrEmpty(m.SupportArea) && m.ExType == 2) > 1) return new Result(false, "默认地址不能大于一个");

            if (templates.IsPinkage == 2) return new Result(true);

            //验证数据正确性
            foreach (var item in list)
            {
                if (item.FirstArticleNum == null) return new Result(false, "首次数量不能为空！");

                if (item.FirstArticlePrice == null) return new Result(false, "首次运费不能为空！");

                if (item.ContinueArticleNum == null) return new Result(false, "续件数量不能为空！");

                if (item.ContinueArticlePrice == null) return new Result(false, "续件运费不能为空!");

                //if (item.ContinueArticlePrice.Value > item.FirstArticlePrice.Value) return new Result(false, "续件运费不能大于首次运费");
            }

            //验证是否重复区域
            var expressList = list.Where(m => m.ExType == 1 && !string.IsNullOrEmpty(m.SupportArea));
            var expressCode = new List<string>();
            foreach (var item in expressList)
            {
                var codes = item.SupportArea.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

                foreach (var c in codes)
                {
                    if (expressCode.Count > 0 && expressCode.Exists(m => m == c)) return new Result(false, "不能添加重复区域！");

                    expressCode.Add(c);
                }
            }

            var emsList = list.Where(m => m.ExType == 2 && !string.IsNullOrEmpty(m.SupportArea));
            var emsCodes = new List<string>();

            foreach (var item in emsList)
            {
                var codes = item.SupportArea.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

                foreach (var c in codes)
                {
                    if (emsCodes.Count > 0 && emsCodes.Exists(m => m == c)) return new Result(false, "不能添加重复区域！");

                    emsCodes.Add(c);
                }
            }

            //验证指定包邮条件
            if (templates.IsPackageMail != null && templates.IsPackageMail.Value)
            {
                if (packList == null || packList.Count <= 0) return new Result(false, "至少选择一个指定包邮地区");

                var packCodes = new List<string>();

                foreach (var item in packList)
                {
                    var codes = item.SupportArea.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

                    foreach (var c in codes)
                    {
                        if (packCodes.Count > 0 && packCodes.Exists(m => m == c)) return new Result(false, "不能添加重复区域！");

                        packCodes.Add(c);
                    }
                }
            }
            return new Result(true);
        }

        #endregion

        #region 逻辑处理

        /// <summary>
        /// 获取当前使用模板，若不存在返回null
        /// </summary>        
        public static T_BAS_Templates CurrentTemplates(Guid? merGuid = null)
        {
            using (var query = Factory.CreateT_BAS_Templates())
            {
                if (merGuid == null)
                {
                    merGuid = CurrentManage.MerchantGuid;
                }
                return query.GetFirstData(m => m.IsActive == true && m.MerchantGuid == merGuid, isFilterMerchant: false);
            }
        }

        /// <summary>
        /// 计算运费
        /// </summary>
        public static PriceResult CalculationFreight(List<OrderConfirm> list, T_BAS_RecieverAddress address)
        {
            if (list == null || list.Count <= 0) return new PriceResult(false, "购买商品不能为空!");

            var areaCode = AreasManage.GetAreaCode(address);
            Dictionary<Guid, T_BAS_Templates> cache = new Dictionary<Guid, T_BAS_Templates>();
            List<TemplateModel> freightList = new List<TemplateModel>();

            //补充规则判断 Bing 160413
            T_BAS_MerchantsAgent mer = null;
            using (var query = Factory.CreateT_BAS_MerchantsAgent())
            {
                mer = query.GetFirstData(c => c.MerchantGuid == CurrentManage.MerchantGuid, isFilterMerchant: false);
            }

            foreach (var item in list)
            {
                var product = Products.ProductsManage.GetEntity(item.id);

                if (product == null) return new PriceResult(false, "不存在商品！");

                var templates = GetCache(product.TemplatesGuid ?? Guid.Empty, cache, mer);
                var templateGuid = templates == null ? Guid.Empty : templates.TemplatesGuid;
                var first = freightList.FirstOrDefault(m => m.TemplateGuid == templateGuid);

                if (first == null)
                {
                    first = new TemplateModel();
                    first.TemplateGuid = templateGuid;
                    first.Tempaltes = templates;
                    first.List = new List<OrderConfirm>();
                    freightList.Add(first);
                }
                first.List.Add(item);
            }

            List<decimal> freights = new List<decimal>();

            foreach (var item in freightList)
            {
                var result = CalculationFreight(item.List, item.Tempaltes, areaCode);

                if (!result.State) return new PriceResult(false, result.Msg);

                freights.Add(result.Price);
            }
            var type = RFrameGenerate.BLL.ParameterManage.GetParamValue(RFrameGenerate.BLL.ParameterName.LogisticsTemplate.LogisticsSum, "0", mer);

            if (type == "0") return new PriceResult(true, freights.Max());

            else if (type == "1") return new PriceResult(true, freights.Min());

            return new PriceResult(true, freights.Sum());
        }

        /// <summary>
        /// 计算运费
        /// </summary>
        public static PriceResult CalculationFreight(List<OrderConfirm> list, Guid addressGuid)
        {
            var address = RecieverAddressManage.GetEntityByGuid(addressGuid);

            return CalculationFreight(list, address);
        }

        /// <summary>
        /// 每个商品计算运费
        /// </summary>
        private static PriceResult CalculationFreight(List<OrderConfirm> list, T_BAS_Templates templates, string areaCode)
        {
            if (list == null || list.Count <= 0) return new PriceResult(false, "购买商品不能为空!");

            //没有设置运费模板
            if (templates == null) return new PriceResult(true, 0.0m);
            //卖家包邮
            if (templates.IsPinkage == 2) return new PriceResult(true, 0.0m);

            var weight = (int)list.Sum(m => m.weight * m.quantity);
            weight = (weight) % 1000 == 0 ? weight / 1000 : (weight / 1000) + 1;
            var total = (int)list.Sum(m => m.quantity);
            var totalPrice = list.Sum(m => m.price * m.quantity);

            //符合包邮条件
            if (PackageMailManage.IsPackageMail(templates, total, totalPrice, areaCode)) return new PriceResult(true, 0.0m);

            var method = ShippingMethodManage.GetShippingMethod(templates.TemplatesGuid, areaCode);

            if (method == null) return new PriceResult(false, "不存在指定运费方式！");

            return ShippingMethodManage.GetFreightByMethod(method, templates.ValuationWay == 1 ? total : weight);
        }

        /// <summary>
        /// 启用模板
        /// </summary>        
        public static Result EnableTemplate(Guid templatesGuid)
        {
            if (templatesGuid == Guid.Empty || !IsExists(templatesGuid)) return new Result(false, "不存在运费模板！");

            using (var query = Factory.CreateT_BAS_Templates())
            {
                query.Update(m => new object[]{
                    m.IsActive == false
                }, v => v.IsActive == true && v.MerchantGuid == CurrentManage.MerchantGuid);

                query.Update(m => new object[]{
                    m.IsActive == true
                }, v => v.MerchantGuid == CurrentManage.MerchantGuid && v.TemplatesGuid == templatesGuid);
            }
            return new Result(true);
        }

        /// <summary>
        /// 禁用模板
        /// </summary>
        public static Result DisableTemplate(Guid templatesGuid)
        {
            if (templatesGuid == Guid.Empty || !IsExists(templatesGuid)) return new Result(false, "不存在运费模板！");

            using (var query = Factory.CreateT_BAS_Templates())
            {
                query.Update(m => new object[]{
                    m.IsActive == false
                }, v => v.MerchantGuid == CurrentManage.MerchantGuid && v.TemplatesGuid == templatesGuid);
            }
            return new Result(true);
        }

        /// <summary>
        /// 是否存在运费模板
        /// </summary>
        public static bool IsExists(Guid templatesGuid)
        {
            using (var query = Factory.CreateT_BAS_Templates())
            {
                return query.IsExist(m => m.TemplatesGuid == templatesGuid);
            }
        }

        public static bool IsUsingTemplate(Guid templateGuid)
        {
            using (var query = Factory.CreateT_BAS_Products())
            {
                return query.IsExist(m => m.TemplatesGuid == templateGuid);
            }
        }

        /// <summary>
        /// 获取数据库查询地区编码
        /// </summary>        
        public static string GetAreaCodeKey(string areaCode)
        {
            if (string.IsNullOrEmpty(areaCode)) return string.Empty;

            return string.Format("|{0}|", areaCode);
        }

        #endregion

        private static T_BAS_Templates GetCache(Guid templateGuid, Dictionary<Guid, T_BAS_Templates> cache, T_BAS_MerchantsAgent mer)
        {
            if (cache.ContainsKey(templateGuid)) return cache[templateGuid];

            T_BAS_Templates templates = null;

            if (templateGuid == Guid.Empty)
            {
                templates = TemplatesManage.CurrentTemplates(mer != null && mer.GoodsDeliveryType == AgentRuleConst.GoodsDeliveryType.总部 ? mer.TopMerchantGuid : null);

            }
            else
            {
                templates = TemplatesManage.GetEntity(templateGuid, mer != null && mer.GoodsDeliveryType == AgentRuleConst.GoodsDeliveryType.总部 ? mer.TopMerchantGuid : null);

            }
            cache.Add(templateGuid, templates);

            return templates;
        }
    }

    public class TemplateModel
    {
        public Guid TemplateGuid { get; set; }
        public T_BAS_Templates Tempaltes { get; set; }
        public List<OrderConfirm> List { get; set; }
    }
}
