using Aliyun.Acs.Core.Logging;
using JiaZhiQuan.Common.Hubs;
using JiaZhiQuan.Common.Messaging;
using JiaZhiQuan.Common.Messaging.Models;
using JiaZhiQuan.Common.Response;
using JiaZhiQuan.Common.Utils;
using Newtonsoft.Json;
using NLog;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using JiaZhiQuan.Common.Models.IM;
using Wicture.DbRESTFul;
using Wicture.DbRESTFul.Infrastructure.Repository;
using static JiaZhiQuan.Common.Models.MallGoodsModel.RefundModel;
using System.Collections;

namespace JiaZhiQuan.Common {
    public static partial class RepositoryExtension
    {
        public static void SendAfterSaleMsg(this DbRESTFulRepository repository, 
            AfterSale refund, DealType dealType, Producer producer) {
            List<ImInfo> imInfos = GetImInfo(refund, dealType);
            if (imInfos.Count == 0) return;
            //写系统消息
            try {
                List<ImInfo> sysMsgs = imInfos.Where(x => x.senderId == (long)UserType.系统).ToList();
                sysMsgs.ForEach(x => _ = producer.ProduceAsync(NotificationModel.GetMsgKey(), new NotificationModel {
                    Type = NotificationType.CommonWithAfterSale,
                    Content = JsonConvert.SerializeObject(new AfterSaleSubModel {
                        UserId = x.acceptId,
                        Message = x.msg,
                        AfterSaleId = x.afterSaleId,
                        ActionLink = $"app://mall/afterSale?afterSaleId={x.afterSaleId}"
                    })
                }));
                //发IM其他消息。
                List<ImInfo> chatMsgs = imInfos.Where(x => x.senderId != (long)UserType.系统).ToList();
                chatMsgs.ForEach(x => _ = producer.ProduceAsync(IMMessageModel.GetMsgKey(), new IMMessageModel {
                    FromUserId = x.senderId,
                    TargetUserId = x.acceptId,
                    Content = new MessageContentDTO {
                        Content = JsonConvert.SerializeObject(new AfterSalesRemindMessageStorageFormat { AfterSaleId = x.afterSaleId, Message = x.msg }),
                        ContentType = MessageContentType.AfterSalesRemind
                    }
                }));
            }catch (Exception ex) { LoggerManager.Logger.Error(ex, "发送售后单状态消息失败：" + ex.Message); }            
        }

        private static List<ImInfo> GetImInfo(AfterSale refund, DealType dealType) {
            string amountStr = BuildYuan(refund.refundOrderAmount);
            string typeStr = BuildTypeDesc(refund.type);
            switch (dealType) {
                case DealType.买家申请退单:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【买家】我发起了{typeStr}申请，等待你处理",
                        afterSaleId = refund.afterSaleId, senderId = refund.userId,
                        acceptId = refund.sellerId,
                    }, };
                case DealType.卖家同意退单:
                    if (refund.type == 1 || refund.type == 2) {
                        return new List<ImInfo>{new ImInfo {
                            msg = $"【系统】卖家已同意退款{amountStr}，钱款将原路退回",
                            afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                            acceptId = refund.userId,
                        } };
                    }
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【卖家】我已发送退货地址，等待你寄回货物。",
                        afterSaleId = refund.afterSaleId, senderId = refund.sellerId,
                        acceptId = refund.userId,
                    } };
                case DealType.卖家超时未处理:
                    if (refund.type == 1 || refund.type == 2) {
                        return new List<ImInfo>{new ImInfo {
                             msg = $"【系统】系统已同意退款{amountStr}，钱款将原路退回。",
                             afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                             acceptId = refund.userId,
                        },new ImInfo {
                             msg = $"【系统】您超时未处理退款，系统已退款{amountStr}给买家。",
                             afterSaleId = refund.afterSaleId, senderId =(long)UserType.系统,
                             acceptId = refund.sellerId,
                        } };
                    }
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】您超时未处理退款，系统已同意退货退款申请，需买家寄回货物，请您尽快发送退货地址。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    },new ImInfo {
                        msg = $"【买家】等待你发送退货地址",
                        afterSaleId = refund.afterSaleId, senderId = refund.userId,
                        acceptId = refund.sellerId,
                    } };
                case DealType.卖家拒绝退单:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【卖家】我拒绝{typeStr}，等待你处理",
                        afterSaleId = refund.afterSaleId, senderId = refund.sellerId,
                        acceptId = refund.userId,
                    } };
                case DealType.买家撤销退单:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】买家已撤销{typeStr}。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    } };
                case DealType.买家超时未申请维权:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】您超时未处理退款，系统关闭了您的{typeStr}申请。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】买家超时未处理退款，系统关闭了买家的{typeStr}申请。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    } };
                case DealType.买家发起维权:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【买家】我已发起{typeStr}维权，双方提交证据中",
                        afterSaleId = refund.afterSaleId, senderId = refund.userId,
                        acceptId = refund.sellerId,
                    },new ImInfo {
                        msg = $"【系统】您发起了{typeStr}维权，双方补充中；" +
                        $"举证结束后平台会介入处理。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】买家发起了{typeStr}维权，" +
                        $"双方补充中，请尽快提交证据，举证结束后平台会介入处理。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    } };
                case DealType.买家退单维权补充证据:
                case DealType.买家货损维权补充证据:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】{refund.eventDesc}",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    } };
                case DealType.卖家退单维权补充证据:
                case DealType.卖家货损维权补充证据:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】{refund.eventDesc}",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    }  };
                case DealType.退单维权买家胜:
                    return new List<ImInfo>{new ImInfo {
                        msg = refund.type==2?$"【系统】平台判定您获胜，同意退款{amountStr}，钱款退回中。":
                        $"【系统】平台判定您获胜，同意{typeStr}" +
                        $"{amountStr}，需您寄回货物，请等待卖家发送退货地址。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = refund.type==2?$"【系统】平台判定买家获胜，已退款{amountStr}给买家。":
                        $"【系统】平台判定买家获胜，已同意退货退款申请，需买家寄回货物，请您尽快发送退货地址。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    }  };
                case DealType.退单维权卖家胜:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】平台判定卖家获胜，系统关闭了您的{typeStr}申请。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】平台判定您获胜，系统关闭了买家的{typeStr}申请。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    }  };
                case DealType.卖家超时未发送退货地址:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】卖家超时未发生退货地址，系统退款" +
                        $"{amountStr}，钱款原路退回中。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】您超时未发生退货地址，系统已退款" +
                        $"{amountStr}给买家。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    }  };
                case DealType.卖家发送退货地址:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【卖家】我已发送退货地址，等待你寄回货物。",
                        afterSaleId = refund.afterSaleId, senderId = refund.sellerId,
                        acceptId = refund.userId, } };
                case DealType.买家超时未寄出退货:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】您超时未寄回货物，系统关闭了您的退货退款申请。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】买家超时未寄回货物，系统关闭了买家的退货退款申请。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    }  };
                case DealType.买家寄出退货:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【买家】我已退货，等待你确认收货",
                        afterSaleId = refund.afterSaleId, senderId = refund.userId,
                        acceptId = refund.sellerId, } };
                case DealType.卖家确认收货:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】退货退款成功，退款{amountStr}原路退回中。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】退货退款成功，已退款{amountStr}给买家。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    }  };
                case DealType.卖家超时未确认收货:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】退货退款成功，退款{amountStr}原路退回中。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】您超时未确认收到退货，系统自动确认收到退货，已退款" +
                        $"{amountStr}给买家。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    }  };
                case DealType.卖家申请货损:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【卖家】我发起了货物损失申请，等待你处理",
                        afterSaleId = refund.afterSaleId, senderId = refund.sellerId,
                        acceptId = refund.userId, } };
                case DealType.买家同意货损:
                    return new List<ImInfo>{
                        new ImInfo {
                        msg = $"【系统】买家已同意货物损失" +
                        $"{amountStr}",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    }  };
                case DealType.买家拒绝货损:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【买家】我拒绝货物损失，等待你处理",
                        afterSaleId = refund.afterSaleId, senderId = refund.userId,
                        acceptId = refund.sellerId, } };
                case DealType.买家超时未处理货损:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】您超时未处理货物损失，系统已同意卖家的货物损失申请。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】买家超时未处理货物损失，系统已同意您的货物损失申请。" +
                        $"{amountStr}给买家。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    }  };
                case DealType.卖家撤销货损:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】卖家已撤销货物损失，退货退款将继续进行。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    } };
                case DealType.卖家超时未申请维权:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】卖家超时未处理货物损失，系统关闭了卖家的货物损失申请，退货退款将继续进行。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】您超时未处理货物损失，系统关闭了您的货物损失申请，退货退款将继续进行。" +
                        $"{amountStr}给买家。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    }  };
                case DealType.卖家发起货损维权:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【卖家】我已发起货物损失维权，双方提交证据中",
                        afterSaleId = refund.afterSaleId, senderId = refund.sellerId,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】卖家发起了货物损失维权，双方补充中，请尽快提交证据，举证结束后平台会介入处理。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】您发起了货物损失维权，双方补充中；举证结束后平台会介入处理。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    } };
                case DealType.货损维权买家胜:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】平台判定您获胜，关闭了卖家的货物损失申请，退货退款将继续进行。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】平台判定买家获胜，关闭了您的货物损失申请，退货退款将继续进行。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    }  };
                case DealType.货损维权卖家胜:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【系统】平台判定卖家获胜，同意货物损失{amountStr}。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.userId,
                    },new ImInfo {
                        msg = $"【系统】平台判定您获胜，同意货物损失{amountStr}。",
                        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                        acceptId = refund.sellerId,
                    }  };
                //case DealType.买家退款失败:
                //    return new List<ImInfo>{new ImInfo {
                //        msg = $"【系统】退款{amountStr}原路退回失败！" +
                //        $"请通过意见反馈或客服电话021-63333317（工作日早9~晚6）联系我们。",
                //        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                //        acceptId = refund.userId,
                //    } };
                //case DealType.买家退款成功:
                //    return new List<ImInfo>{new ImInfo {
                //        msg = $"【系统】您的退款{amountStr}已原路退回，" +
                //        $"可前往支付宝账户{refund.loginName}的账单中查看。",
                //        afterSaleId = refund.afterSaleId, senderId = (long)UserType.系统,
                //        acceptId = refund.userId,
                //    } };
                case DealType.买家提醒卖家收货:
                    return new List<ImInfo>{new ImInfo {
                        msg = $"【买家】请在检查宝贝无误后，及时确认收货",
                        afterSaleId = refund.afterSaleId, senderId = refund.userId,
                        acceptId = refund.sellerId, } };
                default:
                    return new List<ImInfo>();
            }
        }
        private static string BuildYuan(int amount) {
            var yuan = AmountUtils.ConvertCentToYuanStr(amount);
            return $"￥{yuan}";
        }
        private static string BuildTypeDesc(int type) {
            return type switch {
                1 => "退款",
                2 => "退款",
                3 => "退货退款",
                _ => null
            };
        }

        //启用订单03计时器。
        public static async Task<OperateResult> EnableOrderTimer(this DbRESTFulRepository repository,
            long orderId, IDbConnection conn, IDbTransaction trans)
        {
            if (await HasRuningAfterSaleInOrder(repository, orderId, conn, trans))
                return new OperateResult { count = 1 };
            //无进行中的退单，则需要更新订单中的退单完成时间和订单的收货超时时间
            var orderCnt = await repository.QuerySingleOrDefaultAsync<int>(
                $@"update mall_order set refundCompleteAt=@now,receiveExpireAt=date_add(@now, 
                        interval TIMESTAMPDIFF(SECOND, refundCreateAt,receiveExpireAt) SECOND),
                        sysRemindBuyerReceiptTime=date_add(receiveExpireAt,interval -1 day),
                        aftersaleRunningState=0
                       where orderId={orderId} and orderState=3;
                       select row_count();", new { now = DateTime.Now }, conn, trans);
            return new OperateResult { count = orderCnt };
        }

        public static async Task<bool> HasRuningAfterSaleInOrder(this DbRESTFulRepository repository,
            long orderId, IDbConnection conn, IDbTransaction trans) {
            //查询进行中的退单个数
            return (await repository.QuerySingleOrDefaultAsync<long?>(
                $@"select afterSaleId from mall_after_sale where orderId={orderId} 
                   and state>0 and state<>5 limit 1", null, conn, trans) ?? 0) > 0;
        }

        public static async Task<OperateResult> ChangeUserPoints(this DbRESTFulRepository repository,
            long userId, int points, string way, string extra, string desc,
            IDbConnection conn = null, IDbTransaction trans = null)
        {
            var count = 0;
            if (points != 0)
            {
                var data = new { way, extra, desc };
                // 更新价值币总数
                count = await repository.QuerySingleOrDefaultAsync<int>(
                    @$"update n_user_statistic set points=points+{points} 
                    where userId={userId};select row_count();", null, conn, trans);
                // 添加价值币变动记录
                await repository.QueryAsync<dynamic>(
                    @$"insert into n_user_points_record (userId, points, `way`, 
                    extra, description, createAt, createAtDate) values({userId}, 
                    {points}, @way, @extra, @desc, now(), now())", data, conn, trans);
            }

            return new OperateResult { count= count };
        }

        /// <summary>
        /// 卖家超时发货-订单行为
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public static async Task<OperateResult> SellerDeliveryExpire(this DbRESTFulRepository repository,
            long orderId, IDbConnection conn, IDbTransaction trans)
        {
            var count = await repository.QuerySingleOrDefaultAsync<int>(
                $@"update mall_after_sale set state=-1,closeAt=@now where type=1 and state=1 
                         [and orderId=@orderId ];select row_count();",
                new { now = DateTime.Now, orderId }, conn, trans);
            if (count > 0)
            {
                //插入退单事件
                await InsertAfterSaleEventByOrderId(repository, orderId, -1, "系统关闭交易，系统关闭", null, conn, trans);
            }

            return new OperateResult { count = count };
        }

        public static async Task<OperateResult> InsertAfterSaleEventByOrderId(this DbRESTFulRepository repository,
            long orderId, int eventType, string eventDesc, string resourceJson,
            IDbConnection conn = null, IDbTransaction trans = null)
        {
            var eventInfo = new
            {
                eventType, eventDesc,
                resources = resourceJson,
                createAt = DateTime.Now,
            };
            var count = await repository.QuerySingleOrDefaultAsync<int>(
                $@"insert into mall_after_sale_event (afterSaleId,orderId,
                       orderDetailId,eventType,eventDesc,resources,createAt,) 
                        select afterSaleId,orderId,orderDetailId,@eventType,
                       concat(@eventDesc,case when type=1 or type=2 then '退款' else '退货退款' end)
                        ,@resources,@createAt from mall_after_sale
                        where orderId={orderId} and state>0 and state<>5
                       ;select row_count();", eventInfo, conn, trans);
            return new OperateResult { count = count };
        }

        // 退单成功，处理退单结果        
        public static async Task<bool> DealAfterSaleSuccess(this DbRESTFulRepository repository,
            AfterSale refund, long newBillId) {
            var amount = CalRefundAmount(refund);
            using var conn = repository.ConnectionManager.GetConnection();
            conn.Open();
            var trans = conn.BeginTransaction();
            try {
                //插入流水表
                //判断是否存在
                var billId = await repository.QuerySingleOrDefaultAsync<long>(
                    $@"select billId from mall_bill_record where afterSaleId={refund.afterSaleId} 
                        and billType={(int)BillType.退单流水} limit 1 ", null, conn, trans);
                if (billId > 0) return true;
                var cnt = await repository.InsertRefundBill(refund, (object)amount, newBillId, conn, trans);
                if (cnt.count <= 0) return false;
                //插入退款表
                await repository.InsertRefundTask(refund, (object)amount, conn, trans);
                string way = "AFTERSALE", extra = $"{refund.afterSaleId}",
                    desc = $"交易退回-退款{refund.afterSaleId}";
                await repository.ChangeUserPoints((long)refund.userId, (int)amount.points,
                    way, extra, desc, conn, trans);
                trans.Commit();
                return true;
            } catch (Exception ex) {
                trans.Rollback(); throw;
            }
        }

        //判断订单是否全额退货退款
        public static async Task<dynamic> RefundAllForSuccess(this DbRESTFulRepository repository,
            AfterSale refundInfo,long newBillId,long newCashoutId, IDbConnection conn, IDbTransaction trans) {
            var order = await repository.QuerySingleOrDefaultAsync<dynamic>(
                $@"select orderId,orderAmount,serviceAmount from mall_order where orderId={refundInfo.orderId}",
                null, conn, trans);
            List<dynamic> successRefunds = (await repository.QueryAsync<dynamic>(
                $@"select afterSaleId,refundOrderAmount,lossAmount from mall_after_sale 
                where orderId={refundInfo.orderId} and state=5 ",
                null, conn, trans)).ToList();

            var now = DateTime.Now;
            //表示全额退，这里不能考虑货损
            var refundSum = successRefunds.Where(x => x.afterSaleId != refundInfo.afterSaleId)
                .Sum(x => x.refundOrderAmount);
            if (refundInfo.refundOrderAmount == order.orderAmount - refundSum) {
                var orderCnt = await repository.QuerySingleOrDefaultAsync<int>(
                       $@"update mall_order set orderState=4,autoCompletedAt=@now,refundCompleteAt=@now,
                        aftersaleRunningState=0
                       where orderId={refundInfo.orderId} and orderState=3;
                       select row_count();", new { now }, conn, trans);
                if (orderCnt <= 0) throw new Exception("订单异常，无法更新订单状态");

                await repository.MallOrderSellerSettlement((long)refundInfo.orderId, newBillId,
                    newCashoutId);
                return new { count = orderCnt };
            }
            //部分退
            else if (refundInfo.refundOrderAmount < order.orderAmount - refundSum) {
                var count = await repository.EnableOrderTimer((long)refundInfo.orderId, conn, trans);
                if (count.count <= 0) throw new Exception("订单异常，无法启用定时器03");
                return count;
            } else {
                throw new Exception("退单总金额，超过订单总金额。");
            }
        }
        //判断订单是否全额退货退款
        public static async Task<dynamic> RefundAllForClose(this DbRESTFulRepository repository,
            AfterSale refundInfo, IDbConnection conn, IDbTransaction trans) {
            var order = await repository.QuerySingleOrDefaultAsync<dynamic>(
                $@"select orderId,orderAmount,serviceAmount from mall_order where orderId={refundInfo.orderId}",
                null, conn, trans);
            List<dynamic> successRefunds = (await repository.QueryAsync<dynamic>(
                $@"select afterSaleId,refundOrderAmount,lossAmount from mall_after_sale 
                where orderId={refundInfo.orderId} and state=5 ",
                null, conn, trans)).ToList();

            var now = DateTime.Now;
            //表示全额退
            var refundSum = successRefunds.Where(x => x.afterSaleId != refundInfo.afterSaleId)
                .Sum(x => x.refundOrderAmount);
            if (refundInfo.refundOrderAmount == order.orderAmount - refundSum) {
                var orderCnt = await repository.QuerySingleOrDefaultAsync<int>(
                    $@"update mall_order set orderState=-9,closeAt=@now,closeReasonType=4,refundCompleteAt=@now,
                        aftersaleRunningState=0
                       where orderId={refundInfo.orderId} and orderState=3;
                       select row_count();", new { now }, conn, trans);
                if (orderCnt <= 0) throw new Exception("订单异常，无法更新订单状态");
                return new { count = orderCnt };
            }
            //部分退	
            else if (refundInfo.refundOrderAmount < order.orderAmount - refundSum) {
                var count = await repository.EnableOrderTimer((long)refundInfo.orderId, conn, trans);
                if (count.count <= 0) throw new Exception("订单异常，无法启用定时器03");
                return count;
            } else {
                throw new Exception("退单总金额，超过订单总金额。");
            }
        }

        // 插入退单流水
        private static async Task<OperateResult> InsertRefundBill(this DbRESTFulRepository repository,
            AfterSale refund, dynamic amount, long newBillId, IDbConnection conn, IDbTransaction trans) {
            //插入退款流水。           
            var count = await repository.SimpleInsert("mall_bill_record", new {
                billId = newBillId, refund.orderId, refund.userId,
                refund.afterSaleId, billType = (int)BillType.退单流水,
                taskOrderId= $"{refund.orderId}_{refund.afterSaleId}",
                amount.realAmount, billPoints = amount.points,
                pointsDeductionAmount = amount.totalAmount - amount.realAmount,
                billAmount = amount.totalAmount, billState = 1, createAt = DateTime.Now
            }, conn, trans);
            return new OperateResult { count = count.count };
        }

        // 插入退款任务表
        private static async Task<OperateResult> InsertRefundTask(this DbRESTFulRepository repository,
            AfterSale refund, dynamic amount, IDbConnection conn, IDbTransaction trans) {
            if (amount.realAmount <= 0) return new OperateResult { count = 1 };
            var payId = await repository.QuerySingleOrDefaultAsync<string>(
                $@"select payId from mall_order_pay_relation 
                where orderId={refund.orderId}", null, conn, trans);
            if (string.IsNullOrWhiteSpace(payId)) throw new Exception("插入退款任务时，支付单号id不能为空");
            var count = await repository.SimpleInsert("mall_order_refund",
            new {
                id = $"{refund.orderId}_{refund.afterSaleId}", refund.userId, refund.orderId, payId,
                refund.afterSaleId, amount = amount.realAmount, state = 0, createAt = DateTime.Now
            }, conn, trans);
            return new OperateResult { count = count.count };
        }

        private static dynamic CalRefundAmount(AfterSale refund) {
            var totalAmount = refund.refundOrderAmount - refund.lossAmount;
            //这样计算比例会二次失真。不考虑失真问题，向下取分即可。
            var realAmount = (int)(totalAmount * ((double)refund.refundAmount / refund.refundOrderAmount));
            var points = (int)(totalAmount * ((double)refund.refundPoints / refund.refundOrderAmount));
            return new { totalAmount, realAmount, points };
        }

        //根据对象插入表
        public static async Task<InsertResult> SimpleInsert(this DbRESTFulRepository repository,
            string tableName, object insertInfo,
            IDbConnection conn = null, IDbTransaction trans = null)
        {
            var count = new InsertResult { count = 0 };
            if (string.IsNullOrWhiteSpace(tableName) || insertInfo == null) return count;
            if (insertInfo is IEnumerable<dynamic> insertList) {
                if (insertList.Count() == 0) return count;
                var first = insertList.First();

                IDictionary<string, object?> inSet = ExpandoUtils.ConvertToDynamic(first);
                if (inSet.Count == 0) return count;
                var insertSet = inSet.Where(x => x.Value != null);
                string fields = string.Join(",", insertSet.Select(x => x.Key)),
                    valuesFields = string.Join(",", insertSet.Select(x => $"@{x.Key}"));
                string insert = $"({fields}) values({valuesFields})";
                //批量插入的id，获取的不准确。
                string sql = $"insert into {tableName} {insert} ";
                var cnt= await repository.QuerySingleOrDefaultAsync<int>(sql, insertList, conn, trans, false);
                return new InsertResult { count = cnt };
            } else {
                IDictionary<string, object?> inSet = ExpandoUtils.ConvertToDynamic(insertInfo);
                if (inSet.Count == 0) return count;
                var insertSet = inSet.Where(x => x.Value != null);
                string fields = string.Join(",", insertSet.Select(x => x.Key)),
                    valuesFields = string.Join(",", insertSet.Select(x => $"@{x.Key}"));
                string insert = $"({fields}) values({valuesFields})";
                string sql = $"insert into {tableName} {insert} ;select row_count() count,LAST_INSERT_ID() insertId;";
                return await repository.QuerySingleOrDefaultAsync<InsertResult>(sql, insertInfo, conn, trans, false);
            }
        }

        public static async Task<OperateResult> SimpleUpdate(this DbRESTFulRepository repository,
            string tableName, object updateInfo, object condition,
            IDbConnection conn = null, IDbTransaction trans = null, bool updateNull = true) {
            var count = new OperateResult { count = 0 };
            if (string.IsNullOrWhiteSpace(tableName) ||
                updateInfo == null || condition == null) return count;

            IDictionary<string, object?> updateSet = ExpandoUtils.ConvertToDynamic(updateInfo);
            IDictionary<string, object?> conditionSet = ExpandoUtils.ConvertToDynamic(condition);
            if (updateSet.Count == 0 || conditionSet.Count == 0) return count;
            //updateNull为false时，表示不更新空值。
            string upContent = string.Join(",", updateSet.Where(x => updateNull || x.Value != null).
                Select(x => $"{x.Key}=@{x.Key}"));
            string conContent = string.Join(" and ", conditionSet.Select(x => !(x.Value is string)&& x.Value is IEnumerable ?
            $"{x.Key} in @c2{x.Key}" : $"{x.Key}=@c2{x.Key}"));
            string sql = $"update {tableName} set {upContent} where {conContent} ;select row_count();";
            var upObj = new Dictionary<string, object>(updateSet);
            conditionSet.ForEach(x => upObj.Add($"c2{x.Key}", x.Value));
            return new OperateResult { count = await repository.QuerySingleOrDefaultAsync<int>(sql, upObj, conn, trans, false) };
        }
    }
}
