using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYY.Core.Standard.Data.Infrastructure;
using XYY.Service.Standard.Finance.Charging.Base;
using XYY.Service.Standard.Finance.Charging.Express;
using Dapper;
using XYY.Service.Standard.Finance.Charging.CustomerAccount;
using XYY.Core.Standard.Mvc;
using StackExchange.Redis;
using XYY.Core.Standard.Data.Redis;

namespace XYY.Service.Standard.Finance.Charging.CustomerOrderFee
{
    public interface ICustomerOrderFeeOffsetService : IChargesService<ExpressFeechargesModel>
    {
        /// <summary>
        /// 支持内部结算的计算费用
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        Task<ApiJsonModel> ChargeCustomerAndBranchCompany(ExpressFeechargesModel t);
    }

    public class CustomerOrderFeeOffsetService : ICustomerOrderFeeOffsetService
    {

        private IUnitOfWork _unitOfWork;
        ICustomerAccountService _accountService;

        public CustomerOrderFeeOffsetService(IUnitOfWork unitOfWork, ICustomerAccountService accountService)
        {
            _unitOfWork = unitOfWork; _accountService = accountService;

        }

        public async Task<ApiJsonModel> ChargeCustomerAndBranchCompany(ExpressFeechargesModel t)
        {
            string accountNo = t.AccountingNo = $"ANO{DateTime.Now.ToString("yyyyMMddHHmmss")}{t.OrderId}";
            t.AccountingNo = accountNo;
            //先克隆一个，以免计费过程中t的值已被修改
            var tForBranchCompany = t.Copy<ExpressFeechargesModel>();

            var customerResult = await Charges(t);
            tForBranchCompany.CustomerOrderFee = t.CustomerOrderFee;
            if (customerResult.success && t.BranchCompanyCustomerId.HasValue)
            {
                tForBranchCompany.CustomerId = t.BranchCompanyCustomerId.Value;
                tForBranchCompany.IsChargeBranchCompany = true;
                var branchCompanyResult = await Charges(tForBranchCompany);
            }
            return customerResult;
        }

        public async Task<ApiJsonModel> Charges(ExpressFeechargesModel t)
        {
            string key = "";

            if (t.TransactionTime.Kind == DateTimeKind.Utc)
                t.TransactionTime = t.TransactionTime.ToLocalTime();

            if (string.IsNullOrWhiteSpace(t.AccountingNo))
            {
                t.AccountingNo = $"ANO{DateTime.Now.ToString("yyyyMMddHHmmss")}{t.OrderId}";
            }


            ///查询当前计费的冲抵部分
            string sql = @"select * from Finance_ChargesDetail(nolock) where CustomerId=@CustomerId and BillNo=@BillNo and Offset=0  and BillType = '全程派送运费'";

            var changes =
                (await _unitOfWork.QueryBySqlAsync<Finance_ChargesDetail>(sql, param: new { CustomerId = t.CustomerId, BillNo = t.BillNo })).ToList();
            string orderChargesSql = @"select * from Finance_Order_Charges(nolock) where CustomerId=@CustomerId and SystemNo = @BillNo and  Offset=0 ";
            var oldOrderCharges = (await _unitOfWork.QueryBySqlAsync<Finance_Order_Charges>(orderChargesSql, null, new
            {
                CustomerId = t.CustomerId,
                BillNo = t.BillNo
            })).FirstOrDefault();

            if (changes.Count() > 0 && oldOrderCharges != null)
            {
                int[] ids = changes.Select(y => y.Id).ToArray();

                foreach (var item in changes)
                {
                    item.Id = 0;
                    item.FeeDescription = t.FeeDescription + "冲抵" + item.TransactionNo;
                    item.AccountingNo = t.AccountingNo;
                    //按当前时间生成交易号
                    item.TransactionNo = "OF" + DateTime.Now.ToString("yyyyMMddHHmmssfff");
                    item.CreateTime = DateTime.Now;
                    item.TransactionTime = t.TransactionTime;
                    item.AccountingDate = t.TransactionTime;
                    item.BillType = "全程派送运费";
                    item.TransactionType = TransactionType.Consume;
                    item.AmountinOriginalCurrency = item.AmountinOriginalCurrency;
                    item.SettlementAmount = item.SettlementAmount;
                    item.IncomeOrESxpense = "收入";
                    item.Offset = true;
                    item.SettlementCompleted = t.Bookkeeping;
                }
                var newOrderCharges = oldOrderCharges.Copy<Finance_Order_Charges>();
                newOrderCharges.AttachFee = newOrderCharges.AttachFee;
                newOrderCharges.EUTariff = newOrderCharges.EUTariff;
                newOrderCharges.ShippingFee = newOrderCharges.ShippingFee;
                newOrderCharges.TransactionTime = t.TransactionTime;
                newOrderCharges.AccountingNo = t.AccountingNo;
                newOrderCharges.Offset = true;
                newOrderCharges.Weight = t.BillingWeight;
                newOrderCharges.IncomeOrESxpense = "收入";
                newOrderCharges.FeeDescription = t.FeeDescription + "冲抵" + oldOrderCharges.AccountingNo;
                newOrderCharges.SettlementCompleted = t.Bookkeeping;
                if (await SetDB(t, changes, oldOrderCharges, newOrderCharges, ids))
                {
                    return ApiJsonModel.OK(changes);
                }
                else
                {
                    return ApiJsonModel.Error("写入计费信息失败");
                }

            }
            return ApiJsonModel.OK();
        }



        private async Task<bool> SetDB(ExpressFeechargesModel t, List<Finance_ChargesDetail> changes,
            Finance_Order_Charges oldOrderCharges, Finance_Order_Charges newOrderCharges, int[] offSet)
        {

            if (_unitOfWork.Connection.State == System.Data.ConnectionState.Closed)
            {
                _unitOfWork.Connection.Open();
            }
            using (_unitOfWork.Transaction = _unitOfWork.Connection.BeginTransaction())
            {
                try
                {
                    await _unitOfWork
                        .UpdateByConditionAsync<Finance_ChargesDetail, bool>(x => x.Id.In(offSet), new { Offset = true });

                    await _unitOfWork.BulkToDBAsync(changes);

                    await _unitOfWork
                        .UpdateByConditionAsync<Finance_Order_Charges, bool>(x => x.Id == oldOrderCharges.Id
                        , new { Offset = true });

                    await _unitOfWork.InsertAsync(newOrderCharges);
                    ////更新计费表，测试时存在锁同一张记录，我们先注释掉
                    /// 如果想要求更高的性能，计费表可做分表处理
                    //await _unitOfWork.ExecuteAsync("update Order_Fee set OPCFreight =@OPCFreight,AttachFee=@AttachFee,EUTariff=@EUTariff where OrderId=@OrderId", new
                    //{
                    //    OPCFreight = 0,
                    //    AttachFee = 0,
                    //    EUTariff = 0,
                    //    OrderId = t.OrderId
                    //});

                    //更新运费，失败时回滚所有操作
                    if (!await _accountService.Income(t.CustomerId, changes.Sum(x => x.SettlementAmount)))
                    {
                        _unitOfWork.Transaction.Rollback();
                        return false;
                    }
                    else
                    {
                        _unitOfWork.Transaction.Commit();
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    _unitOfWork.Transaction.Rollback();
                    return false;
                }
                finally
                {
                    _unitOfWork.Connection.Close();
                    _unitOfWork.Dispose();
                }
            }
        }
    }

}
