package com.ruoyi.applet.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyl.h5.pojo.request.CancelOrderRequest;
import com.cyl.h5.pojo.request.OrderPayRequest;
import com.cyl.h5.pojo.response.OrderPayResponse;
import com.cyl.h5.pojo.vo.H5OrderVO;
import com.cyl.h5.service.H5CouponService;
import com.cyl.h5.service.H5PetService;
import com.cyl.manager.marketing.mapper.WechatMemberCouponMapper;
import com.cyl.manager.marketing.service.IWechatMemberCouponService;
import com.cyl.manager.oms.convert.AftersaleItemConvert;
import com.cyl.manager.oms.convert.OrderItemConvert;
import com.cyl.manager.oms.domain.*;
import com.cyl.manager.oms.mapper.*;
import com.cyl.manager.oms.service.OmsOrderServiceService;
import com.cyl.manager.oms.service.OrderItemService;
import com.cyl.manager.oms.service.OrderOperateHistoryService;
import com.cyl.manager.pms.mapper.ProductMapper;
import com.cyl.manager.pms.mapper.SkuMapper;
import com.cyl.manager.staff.service.IBondTransactionService;
import com.cyl.manager.staff.service.IStaffService;
import com.cyl.manager.ums.domain.Member;
import com.cyl.manager.ums.domain.MemberWechat;
import com.cyl.manager.ums.mapper.MemberAddressMapper;
import com.cyl.manager.ums.mapper.MemberCartMapper;
import com.cyl.manager.ums.mapper.MemberWechatMapper;
import com.cyl.manager.ums.pojo.vo.PetVO;
import com.cyl.manager.ums.service.PetService;
import com.cyl.tencent.OrderMessageModel;
import com.cyl.wechat.WechatPayData;
import com.cyl.wechat.WechatPayService;
import com.cyl.wechat.WechatPayUtil;
import com.github.pagehelper.PageHelper;
import com.ruoyi.applet.service.IApiMallOrderService;
import com.ruoyi.applet.utils.WechatRefundUtil;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisService;
import com.ruoyi.common.utils.IDGenerator;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.config.LocalDataUtil;
import com.ruoyi.model.domain.AppletOrder;
import com.ruoyi.model.domain.AppletOrderDateFrequency;
import com.ruoyi.model.domain.AppletOrderItem;
import com.ruoyi.model.domain.OmsOrderEvaluation;
import com.ruoyi.model.service.IAppletOrderDateFrequencyService;
import com.ruoyi.model.service.IAppletOrderItemService;
import com.ruoyi.model.service.IAppletOrderService;
import com.ruoyi.model.service.IOmsOrderEvaluationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class IApiMallOrderServiceImpl implements IApiMallOrderService {

    @Autowired
    private MemberAddressMapper memberAddressMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private MemberCartMapper memberCartMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OmsOrderServiceMapper omsOrderServiceMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private OrderOperateHistoryMapper orderOperateHistoryMapper;
    @Autowired
//    @Lazy
    private WechatPayService wechatPayService;




    @Autowired
    private MemberWechatMapper memberWechatMapper;

    @Autowired
    private OrderOperateHistoryService orderOperateHistoryService;


    @Autowired
    private WechatPaymentHistoryMapper wechatPaymentHistoryMapper;

    private AftersaleMapper aftersaleMapper;

    @Autowired
    private AftersaleItemMapper aftersaleItemMapper;


    @Autowired
    private OmsOrderServiceService omsOrderServiceService;



    @Autowired
    private WechatMemberCouponMapper wechatMemberCouponMapper;

    @Autowired
    private WechatRefundUtil wechatRefundUtil;


    @Autowired
    private H5PetService h5PetService;

    @Autowired
    private IAppletOrderService appletOrderService;

    @Autowired
    private IAppletOrderItemService appletOrderItemService;

    @Autowired
    private IOmsOrderEvaluationService orderEvaluationService;

    @Autowired
    private IAppletOrderDateFrequencyService appletOrderDateFrequencyService;

    //下单端小程序 - 查看订单列表信息
    @Override
    public PageImpl<H5OrderVO> orderPageByOpenid(List<Integer> status, String openId, Pageable pageable){
        QueryWrapper<MemberWechat> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("routine_openid", openId);
        MemberWechat memberWechat = memberWechatMapper.selectOne(queryWrapper);

        if (memberWechat == null) {
            return new PageImpl<>(Collections.EMPTY_LIST, pageable, 0);
        }

        if (pageable != null){
            PageHelper.startPage(pageable.getPageNumber() + 1, pageable.getPageSize());
        }

        List<H5OrderVO> orderList = orderMapper.orderPage3(status, memberWechat.getMemberId());


//        List<H5OrderVO> orderList = orderMapper.selectList(Wrappers.<Order>lambdaQuery()
//                .in(Order::getStatus, status)
//                .orderByDesc(Order::getCreateTime))
//                .stream().map(n -> {
//                    H5OrderVO h5OrderVO = new H5OrderVO();
//                    BeanUtils.copyProperties(n, h5OrderVO);
//                    h5OrderVO.setOrderId(n.getId());
//                    return h5OrderVO;
//                }).collect(Collectors.toList());


        long total = ((com.github.pagehelper.Page) orderList).getTotal();
        // 两个list都没数据那肯定返回空了
        if (CollectionUtil.isEmpty(orderList)){
            return new PageImpl<>(Collections.EMPTY_LIST, pageable, 0);
        }
        // 开始组装item了
        // 拿出所有orderId，查item，然后分组 by orderId
        List<Long> idList = new ArrayList<>();

        if (CollectionUtil.isNotEmpty(orderList)){
            idList.addAll(orderList.stream().map(H5OrderVO::getOrderId).collect(Collectors.toList()));
        }

        for (Long item : idList){
            System.out.println("这个东西是什么：======："+item);
        }
        QueryWrapper<OrderItem> orderItemQw = new QueryWrapper<>();
        orderItemQw.in("order_id", idList);
        Map<Long, List<OrderItem>> orderItemMap =
                orderItemMapper.selectList(orderItemQw).stream().collect(Collectors.groupingBy(OrderItem::getOrderId));


        orderList.forEach(item -> {

            item.setOrderItemList(orderItemMap.get(item.getOrderId()));

            OmsOrderService orderServiceInfo = omsOrderServiceService.selectByOrderId(item.getOrderId());
            PetVO petVO = h5PetService.selectPetById(orderServiceInfo.getPetId());
            orderServiceInfo.setPetVo(petVO);
            item.setService(orderServiceInfo);


            OmsOrderService omsOrderService = new OmsOrderService();
            omsOrderService.setOrderId(item.getOrderId());
            List<OmsOrderService> orderServiceList = omsOrderServiceMapper.selectListBySql(omsOrderService);


            // 使用一个 Set 来跟踪已经添加的 PetVO 的 id
            Set<Integer> addedPetIds = new HashSet<>();
            List<PetVO> petVOList = new ArrayList<>();

            for (OmsOrderService service1 : orderServiceList) {
                // 宠物标识不为空的时候查询数据
                if (service1.getPetId() != null) {
                    PetVO petVO1 = h5PetService.selectPetById(service1.getPetId());

                    // 检查 petVO 的 id 是否已经添加过
                    if (petVO1 != null && !addedPetIds.contains(petVO1.getId())) {
                        service1.setPetVo(petVO1);
                        petVOList.add(petVO1);
                        addedPetIds.add(petVO1.getId()); // 标记该 id 已添加
                    }
                }
            }
            item.setOrderServiceList(orderServiceList);
            item.setPetVOList(petVOList);

//            item.setUsersTeacher(appletUsersTeacherService.selectAppletUsersTeacherById(item.getTeacherId()));


        });

        return new PageImpl<>(orderList, pageable, total);
    }



    //下单小程序端 - 根据订单标识查询订单详情
    @Override
    public H5OrderVO orderDetail(Long orderId){
        H5OrderVO order = orderMapper.selectOrderDetail(orderId);
        if (order == null){
            throw new RuntimeException("未查询到该订单");
        }
        // 组装item
        QueryWrapper<OrderItem> orderItemQw = new QueryWrapper<>();
        orderItemQw.eq("order_id", orderId);
        List<OrderItem> orderItemList = orderItemMapper.selectList(orderItemQw);
        order.setOrderItemList(orderItemList);

        //组装order_service
        OmsOrderService omsOrderService = new OmsOrderService();
        omsOrderService.setOrderId(orderId);
        List<OmsOrderService> orderServiceList = omsOrderServiceMapper.selectListBySql(omsOrderService);
        order.setOrderServiceList(orderServiceList);


        List<OmsOrderService> service = orderServiceList;
        // 使用一个 Set 来跟踪已经添加的 PetVO 的 id
        Set<Integer> addedPetIds = new HashSet<>();
        List<PetVO> petVOList = new ArrayList<>();
        for (OmsOrderService service1 : service) {
            // 宠物标识不为空的时候查询数据
            if (service1.getPetId() != null) {
                PetVO petVO = h5PetService.selectPetById(service1.getPetId());
                // 检查 petVO 的 id 是否已经添加过
                if (petVO != null && !addedPetIds.contains(petVO.getId())) {
                    service1.setPetVo(petVO);
                    petVOList.add(petVO);
                    addedPetIds.add(petVO.getId()); // 标记该 id 已添加
                }
            }

        }
        order.setPetVOList(petVOList);

        // 如果未付款，计算倒计时
        if (Constants.OrderStatus.NOTPAID.equals(order.getStatus())){
            // 订单超时时间900s，后面可以配置到字典等
            Integer time = 900;
            Date addDate = Date.from(order.getCreateTime().plusSeconds(time).atZone(ZoneId.systemDefault()).toInstant());
            if (addDate.after(new Date())) {
                order.setTimeToPay(addDate.getTime());
            }
        }
        return order;
    }


    //下单小程序端 - 根据订单标识取消订单
    @Transactional
    @Override
    public  String orderBatchCancel(CancelOrderRequest request, Long userId) {
//        LocalDateTime optDate = LocalDateTime.now();
//        if (CollectionUtil.isEmpty(request.getIdList())){
//            throw new RuntimeException("未指定需要取消的订单号");
//        }
//        QueryWrapper<Order> orderQw = new QueryWrapper<>();
//        orderQw.in("id", request.getIdList());
//        List<Order> orderList = orderMapper.selectList(orderQw);
//        if (orderList.size() < request.getIdList().size()){
//            throw new RuntimeException("未查询到订单信息");
//        }
//        //查orderItem
//        QueryWrapper<OrderItem> qw = new QueryWrapper<>();
//        qw.in("order_id", request.getIdList());
//        List<OrderItem> orderItem = orderItemMapper.selectList(qw);
//        if (CollectionUtil.isEmpty(orderItem)) {
//            throw new RuntimeException("未查询到订单信息");
//        }
//        long count = orderList.stream().filter(it -> !Constants.H5OrderStatus.UN_PAY.equals(it.getStatus())).count();
//        if (count > 0){
//            throw new RuntimeException("订单状态已更新，请刷新页面");
//        }
//        List<OrderOperateHistory> addHistoryList = new ArrayList<>();
//        orderList.forEach(item -> {
//            item.setStatus(Constants.H5OrderStatus.CLOSED);
//            item.setUpdateTime(optDate);
//            item.setUpdateBy(userId);
//            OrderOperateHistory history = new OrderOperateHistory();
//            history.setOrderId(item.getId());
//            history.setOrderSn(item.getOrderSn());
//            history.setOperateMan(userId == null ? "后台管理员" : "" + item.getMemberId());
//            history.setOrderStatus(Constants.H5OrderStatus.CLOSED);
//            history.setCreateTime(optDate);
//            history.setCreateBy(userId);
//            history.setUpdateBy(userId);
//            history.setUpdateTime(optDate);
//            addHistoryList.add(history);
//
//        });
//        //取消订单
//        int rows = orderMapper.cancelBatch(orderList);
//        if (rows < 1){
//            throw new RuntimeException("更改订单状态失败");
//        }
//        orderItem.stream().collect(Collectors.groupingBy(it->it.getSkuId())).forEach((k,v)->{
//            AtomicReference<Integer> totalCount = new AtomicReference<>(0);
//            v.forEach(it-> totalCount.updateAndGet(v1 -> v1 + it.getQuantity()));
//            skuMapper.updateStockById(k, optDate, -1 * totalCount.get());
//        });
//
//        //创建订单操作记录
//        boolean flag = orderOperateHistoryService.saveBatch(addHistoryList);
//        if (!flag){
//            throw new RuntimeException("创建订单操作记录失败");
//        }


        Order order = orderMapper.selectById(request.getId());

        Integer oldOrderStatus = order.getStatus();

        orderMapper.cancelBatchOne(request.getId());

        if (oldOrderStatus == 0){
            return "";
        }

        //取消派单
//        appletOrderService.remove(Wrappers.<AppletOrder>lambdaQuery()
//                .eq(AppletOrder::getOrderId, order.getId()));

        List<AppletOrder> list = appletOrderService.lambdaQuery()
                .eq(AppletOrder::getOrderId, order.getId())
                .list();

        for (AppletOrder appletOrder : list) {
            appletOrder.setStatus(2);//取消派单
            appletOrderService.updateById(appletOrder);
        }

        //取消日订单
        appletOrderItemService.remove(Wrappers.<AppletOrderItem>lambdaQuery()
                .eq(AppletOrderItem::getOrderId, order.getId()));

        //取消日订单
        appletOrderDateFrequencyService.remove(Wrappers.<AppletOrderDateFrequency>lambdaQuery()
                .eq(AppletOrderDateFrequency::getOrderId, order.getId()));

        String refundResult = applyWechatRefund(order, request.getRemark());

        return "取消订单成功";
    }

    /**
     * 申请微信退款
     * @param order 订单信息
     * @param reason 退款原因
     * @return 退款结果
     */
    private String applyWechatRefund(Order order, String reason) {
            // 构建退款请求
            WechatRefundUtil.RefundRequest refundRequest = new WechatRefundUtil.RefundRequest();

            // 设置退款参数
            refundRequest.out_trade_no = String.valueOf(order.getPayId()); // 商户订单号
            refundRequest.out_refund_no = "REFUND_" + System.currentTimeMillis(); // 商户退款单号 out_refund_no
            refundRequest.reason =  StringUtils.isNotEmpty(reason) ? reason : "用户取消订单"; // 退款原因
            refundRequest.notify_url = WechatPayData.notifyUrl + "/refund"; // 退款通知地址

            // 设置退款金额
            WechatRefundUtil.AmountReq amountReq = new WechatRefundUtil.AmountReq();
//            amountReq.refund = order.getPayAmount().multiply(new BigDecimal(100)).longValue(); // 退款金额（分）
//            amountReq.total = order.getPayAmount().multiply(new BigDecimal(100)).longValue(); // 原订单金额（分）

            amountReq.refund = 1L; // 退款金额（分）
            amountReq.total = 1L; // 原订单金额（分）

            amountReq.currency = "CNY"; // 货币类型
            refundRequest.amount = amountReq;

            // 设置资金账户
            refundRequest.funds_account = WechatRefundUtil.ReqFundsAccount.AVAILABLE;

            // 调用退款接口
            WechatRefundUtil.RefundResponse refundResponse = wechatRefundUtil.applyRefund(refundRequest);

            // 记录退款历史
            recordRefundHistory(order, refundResponse, reason);

            return "退款申请成功，退款单号：" + refundResponse.outRefundNo;
    }

    /**
     * 记录退款历史
     * @param order 订单信息
     * @param refundResponse 退款响应
     * @param reason 退款原因
     */
    private void recordRefundHistory(Order order, WechatRefundUtil.RefundResponse refundResponse, String reason) {
        try {
            WechatPaymentHistory refundHistory = new WechatPaymentHistory();
            refundHistory.setOrderId(order.getId());
            refundHistory.setMemberId(order.getMemberId());
            refundHistory.setTitle("订单退款");
            refundHistory.setMoney(order.getPayAmount());
            refundHistory.setOpType(Constants.PaymentOpType.REFUND);
            refundHistory.setPaymentStatus(Constants.PaymentStatus.INCOMPLETE);
            refundHistory.setRemark(reason != null ? reason : "用户取消订单");
            refundHistory.setAttach(refundResponse.refundId);
            refundHistory.setResponseBody(JSONObject.toJSONString(refundResponse));
            refundHistory.setCreateTime(LocalDateTime.now());
            refundHistory.setUpdateTime(LocalDateTime.now());

             wechatPaymentHistoryMapper.insert(refundHistory);
            log.info("退款历史记录已创建：{}", refundHistory);
        } catch (Exception e) {
            log.error("记录退款历史失败", e);
        }
    }


    //下单小程序端 - 根据订单标识去评价
    @Override
    public OmsOrderEvaluation orderEvaluate(OmsOrderEvaluation evaluation){

        orderEvaluationService.save(evaluation);

        return evaluation;
    }



    @Override
    public OrderPayResponse orderPay(OrderPayRequest req) {
        QueryWrapper<Order> qw = new QueryWrapper<>();
        qw.eq("pay_id", req.getPayId());
        qw.eq("status", 0);
        List<Order> orderList = orderMapper.selectList(qw);
        if (CollectionUtil.isEmpty(orderList)){
            throw new RuntimeException("没有待支付的订单");
        }
        QueryWrapper<MemberWechat> memberWechatQw = new QueryWrapper<>();
        memberWechatQw.eq("member_id", req.getMemberId());
        MemberWechat memberWechat = memberWechatMapper.selectOne(memberWechatQw);
        if (memberWechat == null || StrUtil.isBlank(memberWechat.getRoutineOpenid())){
            throw new RuntimeException("获取用户openId失败");
        }

        Order order = orderList.get(0);


        QueryWrapper<OrderItem> orderItemQw = new QueryWrapper<>();
        orderItemQw.eq("order_id", order.getId());
        List<OrderItem> orderItemList = orderItemMapper.selectList(orderItemQw);
        String orderDesc = orderItemList.get(0).getProductName().substring(0, Math.min(40, orderItemList.get(0).getProductName().length()));
        //保存微信支付历史
        LocalDateTime optDate = LocalDateTime.now();
        QueryWrapper<WechatPaymentHistory> wxPaymentQw = new QueryWrapper<>();
        wxPaymentQw.eq("order_id", order.getPayId());
        wxPaymentQw.eq("op_type", Constants.PaymentOpType.PAY);
//        WechatPaymentHistory wechatPaymentHistory = wechatPaymentHistoryMapper.selectOne(wxPaymentQw);
//        if (wechatPaymentHistory == null){

            Long payId = IDGenerator.generateId();

            WechatPaymentHistory wechatPaymentHistory = new WechatPaymentHistory();
            wechatPaymentHistory.setPayId(payId);
            wechatPaymentHistory.setOrderId(order.getId());
            wechatPaymentHistory.setMemberId(req.getMemberId());
            wechatPaymentHistory.setOpenid(memberWechat.getRoutineOpenid());
            wechatPaymentHistory.setTitle(orderItemList.get(0).getProductName());
            wechatPaymentHistory.setMoney(order.getPayAmount());
            wechatPaymentHistory.setOpType(Constants.PaymentOpType.PAY);
            wechatPaymentHistory.setPaymentStatus(0);
            wechatPaymentHistory.setCreateBy(req.getMemberId());
            wechatPaymentHistory.setCreateTime(optDate);
            wechatPaymentHistory.setUpdateBy(req.getMemberId());
            wechatPaymentHistory.setUpdateTime(optDate);
            wechatPaymentHistoryMapper.insert(wechatPaymentHistory);


            req.setPayId(payId);
            order.setPayId(payId);
            orderMapper.updateById(order);

//        }else {
//            wechatPaymentHistory.setMoney(order.getPayAmount());
//            wechatPaymentHistoryMapper.updateById(wechatPaymentHistory);
//        }
        //请开启微信支付 wechat.enabled=true
        //调用wx的jsapi拿prepayId，返回签名等信息
        String openId = memberWechat.getOpenid();
        String appId = WechatPayData.appId;
        if (2 == req.getWechatType()) {
            openId = memberWechat.getRoutineOpenid();
            appId = WechatPayData.miniProgramAppId;
        }
        String prepayId = wechatPayService.jsapiPay(
                String.valueOf(req.getPayId()),
                orderDesc,
//                Integer.valueOf(orderList.stream().map(Order::getPayAmount).
//                        reduce(BigDecimal.ZERO, BigDecimal::add).multiply(new BigDecimal(100)).stripTrailingZeros().toPlainString()),
                1,
                openId,
                req.getMemberId(),
                appId
        );

        /*
        String prepayId = wechatPayService.jsapiPay(
                String.valueOf(order.getPayId()),
                orderDesc,
                Integer.valueOf(payAmount),
                openId,
                member.getId(),
                appId
        );
        **/

        OrderPayResponse response = new OrderPayResponse();
        response.setPayType(2);
        String nonceStr = WechatPayUtil.generateNonceStr();
        long timeStamp = WechatPayUtil.getCurrentTimestamp();
        prepayId = "prepay_id=" + prepayId;
        String signType = "RSA";
        String paySign = null;
        String signatureStr = Stream.of(appId, String.valueOf(timeStamp), nonceStr, prepayId)
                .collect(Collectors.joining("\n", "", "\n"));
        try {
            paySign = WechatPayUtil.getSign(signatureStr, WechatPayData.privateKeyPath);
        } catch (Exception e) {
            throw new RuntimeException("支付失败");
        }
        response.setAppId(appId);
        response.setTimeStamp(String.valueOf(timeStamp));
        response.setNonceStr(nonceStr);
        response.setSignType(signType);
        response.setPackage_(prepayId);
        response.setPaySign(paySign);
        response.setOrderId(orderList.get(0).getId());
        return response;
    }

}
