using RFrameGenerate.BLL;
using RFrameGenerate.DAL.Enums;
using RFrameGenerate.Model;
using RFramework.SQLServer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RFramework.SQLQuery;

namespace jiouosdptask.BLL
{
    /// <summary>
    /// 贡献值
    /// </summary>
    public class Contribution
    {
        public static void Run()
        {
            GridModel gridModel = new GridModel() { page = 1, rows = 100, };
            using (var tran = new SqlRTransaction())
            {
                var query_merchants = Factory.CreateT_BAS_Merchants(tran);
                var query_order = Factory.CreateT_BAS_Orders(tran);
                var query_procedure = Factory.CreateProcedure(tran);
                var query_disProp = Factory.CreateT_BAS_DistributionProp(tran);
                var query_disType = Factory.CreateT_BAS_DistributionType(tran);

                var types = query_disType.GetList(null, false, v => v.Value, OrderMethods.DESC, isFilterMerchant: false);
                if (types == null) types = new List<T_BAS_DistributionType>();

                while (true)
                {
                    var list = query_merchants.GetPageList(gridModel, v => v.IsEnable == true, orderExpression: o => o.MerchantGuid);

                    if (list == null || list.Count <= 0)
                    {
                        GC.Collect();
                        break;
                    }

                    list.ForEach(m =>
                    {
                        var contributeList = new List<PT_Statistics_Distribute_Contribution>();

                        var _orderList = query_procedure.GetDistributeContribution(m.MerchantGuid);

                        if (_orderList != null && _orderList.Count > 0)
                        {
                            #region 获取分销商列表
                            contributeList.AddRange(_orderList);

                            var parents = contributeList.Where(v => v.ParentGuid != null && v.ParentGuid != Guid.Empty).Select(v => v.ParentGuid.Value).Distinct().ToArray();
                            var ids = GetNotExists(parents, contributeList);

                            while (ids != null && ids.Length > 0)
                            {
                                var addList = query_disProp.GetList(c => c.DistributionPropGuid.SqlIn(ids), isFilterMerchant: false);

                                if (addList == null || addList.Count <= 0) break;

                                addList.ForEach(v =>
                                {
                                    contributeList.Add(new PT_Statistics_Distribute_Contribution()
                                    {
                                        DistributionPropGuid = v.DistributionPropGuid,
                                        PayMoney = 0.0m,
                                        ParentGuid = v.ParentDistributionPropGuid
                                    });
                                });

                                parents = contributeList.Where(v => v.ParentGuid != null && v.ParentGuid != Guid.Empty).Select(v => v.ParentGuid.Value).Distinct().ToArray();
                                ids = GetNotExists(parents, contributeList);
                            }

                            #endregion

                            foreach (var item in contributeList)
                            {
                                item.TotalAmount = GetTotal(item.DistributionPropGuid, contributeList);
                                var type = types.FirstOrDefault(v => v.Value < item.TotalAmount && v.MerchantGuid == m.MerchantGuid);
                                if (type == null)
                                {
                                    query_disProp.Update(v => new object[] { v.ContributeValue == item.TotalAmount, v.DistributionTypeGuid == null }, v => v.DistributionPropGuid == item.DistributionPropGuid, false);
                                }
                                else
                                {
                                    query_disProp.Update(v => new object[] { v.ContributeValue == item.TotalAmount, v.DistributionTypeGuid == type.DistributionTypeGuid }, v => v.DistributionPropGuid == item.DistributionPropGuid, false);
                                }
                            }
                        }
                    });

                    gridModel.page++;
                }
            }
        }

        private static Guid[] GetNotExists(Guid[] ids, List<PT_Statistics_Distribute_Contribution> list)
        {
            if (ids == null || ids.Length <= 0) return new Guid[0];

            List<Guid> array = new List<Guid>();

            foreach (var item in ids)
            {
                if (list.Exists(m => m.DistributionPropGuid == item)) continue;

                array.Add(item);
            }

            return array.ToArray();
        }

        private static decimal GetTotal(Guid id, List<PT_Statistics_Distribute_Contribution> contributionList)
        {
            var item = contributionList.FirstOrDefault(m => m.DistributionPropGuid == id);

            if (item == null) return 0.0m;

            var total = item.PayMoney;

            var list = contributionList.Where(m => m.ParentGuid == id);

            List<Guid> exists = new List<Guid>();
            while (list != null && list.FirstOrDefault() != null)
            {
                var sum = list.Sum(m => m.PayMoney);
                total += sum;

                var ids = list.Select(m => m.DistributionPropGuid).ToArray();
                if (exists.Exists(m => ids.Contains(m)))
                {
                    using (var query = Factory.CreateT_BAS_ContributionError())
                    {
                        query.Add(new T_BAS_ContributionError()
                        {
                            ContributionErrorGuid = Guid.NewGuid(),
                            DistributionPropGuid = id,
                            OperationTime = DateTime.Now
                        });
                    }
                    return default(decimal);
                }
                else
                {
                    exists.AddRange(ids);
                }
                list = contributionList.Where(m => m.ParentGuid != null && m.ParentGuid != Guid.Empty && ids.Contains(m.ParentGuid.Value));
            }

            return total;
        }
    }
}
