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.Order.OrderReturn.Dto;
using Dapper;
using XYY.Model.Standard.Order;
using XYY.Model.Standard.Channel;
using XYY.Service.Standard.Finance.Charging.CustomerOrderFee;
using XYY.Service.Standard.Finance.Charging.Express;
using XYY.Model.Standard;

namespace XYY.Service.Standard.Order
{
    public interface IOrderReturnService
    {
        Task<CNOrderReturnResult> PostReturn(CNOrderReturnOption option);
    }

    public class OrderReturnService : IOrderReturnService
    {

        private IUnitOfWork _unitOfWork;
        ICustomerOrderFeeOffsetService _customerOrderFeeOffsetService;


        public OrderReturnService(IUnitOfWork unitOfWork, ICustomerOrderFeeOffsetService customerOrderFeeOffsetService)
        {
            _unitOfWork = unitOfWork;
            _customerOrderFeeOffsetService = customerOrderFeeOffsetService;
        }

        public async Task<CNOrderReturnResult> PostReturn(CNOrderReturnOption option)
        {
            if (option.Check.IsCheckCustomerId && option.Check.CustomerId <= 0)
                throw new Exception("未选择需校验客户");
            var orders =
                await _unitOfWork.QueryBySqlAsync<Order_Order>("select TransferNumber,TrackingNumber,SystemNo,Id,OrderStatus,CustomerId from order_order(nolock) where TrackingNumber in @TrackingNumbers", null,
                new { TrackingNumbers = option.Models.Select(x => x.TrackingNumber) });

            IEnumerable<CustomerInfo> customers = await GetCustomersOfOrder(orders);

            var result = new CNOrderReturnResult
            {
                Items = option.Models.Select(x => new CNOrderReturnResultItem
                {
                    IsSuccess = true,
                    TrackingNumber = x.TrackingNumber
                }).ToList()
            };
            foreach (var noAny in result.Items.Where(x => !orders.Any(y => y.TrackingNumber == x.TrackingNumber)))
            {
                noAny.IsSuccess = false;
                noAny.Message = "在系统内未找到相关订单";
            }
            List<Order_Return> PostOrderReturn = new List<Order_Return>();
            List<Order_Question> PostOrderQuestion = new List<Order_Question>();
            List<ExpressFeechargesModel> offSetCharges = new List<ExpressFeechargesModel>();
            foreach (var item in result.Items.Where(x => x.IsSuccess))
            {
                var o = orders.First(x => x.TrackingNumber == item.TrackingNumber);
                if (o.OrderStatus == 4)
                {
                    item.IsSuccess = false;
                    item.Message = "订单已退件，勿重复操作";
                }
                else if (o.OrderStatus == 3)
                {
                    item.IsSuccess = false;
                    item.Message = "订单已装箱，无法退件";
                }
                else if (o.OrderStatus < 1)
                {
                    item.IsSuccess = false;
                    item.Message = "订单已删除，无法退件";
                }
                else if (option.Check.IsCheckCustomerId && o.CustomerId != option.Check.CustomerId)
                {
                    item.IsSuccess = false;
                    item.Message = "当前操作的订单与校验客户对不上";
                }
                else
                {
                    string message = option.Models.First(x => x.TrackingNumber == item.TrackingNumber).Message;
                    PostOrderReturn.Add(new Order_Return
                    {
                        OrderId = o.Id,
                        TrackingNumber = item.TrackingNumber,
                        Remark = message,
                        CreateTime = DateTime.Now
                    });

                    PostOrderQuestion.Add(new Order_Question
                    {
                        OrderId = o.Id,
                        TrackingNumber = item.TrackingNumber,
                        TransferNumber = o.TransferNumber,
                        Question = message,
                        CreateTime = DateTime.Now
                    });

                    offSetCharges.Add(new ExpressFeechargesModel
                    {
                        OrderId = o.Id,
                        BillNo = o.SystemNo,
                        FeeDescription = "退件",
                        CustomerId = o.CustomerId,
                        Bookkeeping = false,
                        TransactionTime = DateTime.Now,
                        BranchCompanyCustomerId = 0
                    });
                }
            }
            //检验完成，实际操作
            if (_unitOfWork.Connection.State != System.Data.ConnectionState.Open)
                _unitOfWork.Connection.Open();
            _unitOfWork.Transaction = _unitOfWork.Connection.BeginTransaction();


            //开启事务
            try
            {
                int[] ids = PostOrderReturn.Select(x => x.OrderId).ToArray();
                //订单状态
                _unitOfWork.Connection.ExecuteScalar("update order_order set OrderStatus=4 where id in @ids", new { ids = ids }, _unitOfWork.Transaction);
                //写入操作日志
                await _unitOfWork.BulkToDBAsync(PostOrderQuestion);
                //写入退件日志
                await _unitOfWork.BulkToDBAsync(PostOrderReturn);
                _unitOfWork.Commit();
            }
            catch (Exception ex)
            {
                _unitOfWork.Rollback();
                throw ex;
            }
            finally
            {
                _unitOfWork.Connection.Close();
            }


            foreach (var offsetCharge in offSetCharges)
            {
                var customer = customers.FirstOrDefault(c => c.Id == offsetCharge.CustomerId);
                if (customer != null)
                {
                    offsetCharge.BranchCompanyCustomerId = customer.BranchCompanyId;
                    offsetCharge.Bookkeeping = customer.DeductionNode == XYY.Model.Standard.User.Enums.DeductionNode.实时扣费;
                    var r = await _customerOrderFeeOffsetService.ChargeCustomerAndBranchCompany(offsetCharge);
                    if (!r.success)
                        throw new Exception(r.error);
                }

            }

            return result;
        }

        private async Task<IEnumerable<CustomerInfo>> GetCustomersOfOrder(IEnumerable<Order_Order> orders)
        {
            if (orders?.Any() == true)
            {
                var customerIds = orders.Select(i => i.CustomerId);
                var customers = await _unitOfWork.QueryBySqlAsync<CustomerInfo>("select * from User_Customer(nolock) where Id in @Ids", param: new { Ids = customerIds });
                return customers;
            }
            else return null;
        }
    }
}
