package com.ruoyi.app.pay;


import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.app.order.dto.OrderPushBodyDto;
import com.ruoyi.app.utils.*;
import com.ruoyi.app.utils.event.PushEventService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.vo.PayResponse;
import com.ruoyi.system.domain.vo.PayVN;
import com.ruoyi.system.mapper.RiderPositionMapper;
import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.Auth;
import com.ruoyi.system.utils.JwtUtil;
import lombok.SneakyThrows;
import org.apache.poi.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static java.lang.Thread.sleep;

@RestController
@RequestMapping("/pay")
public class PayController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(PayController.class);
    @Autowired
    private IPosOrderService posOrderService;
    @Autowired
    private IInfoUserService infoUserService;
    @Autowired
    private IUserMarginService userMarginService;
    @Autowired
    private IUserBillingService userBillingService;
    @Autowired
    private IIpnLogService ipnLogService;
    @Autowired
    private RiderPositionMapper riderPositionMapper;
    @Autowired
    private PushEventService pushEventService;


    //VNPay
    @Anonymous
    @Auth
    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
    @RequestMapping(value = "/VNPay", method = {RequestMethod.GET, RequestMethod.POST})
    public AjaxResult VNPay(@RequestParam(defaultValue = "") String language, @RequestParam String orderid, @RequestParam String amount, HttpServletRequest request) {

        IpUtils ipUtils = new IpUtils();
        String ip = ipUtils.getIpAddr(request);
        Md5Pay md5Pay = new Md5Pay();
        String obj = md5Pay.VNPay(language, orderid, amount, ip);
        QueryWrapper<PosOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("dd_id", orderid);
        PosOrder posOrder = posOrderService.getOne(wrapper);
        if (posOrder == null) {
            return error(MessageUtils.message("no.order.id.error"));
        } else {
            PosOrder pos = new PosOrder();
            pos.setId(posOrder.getId());
            pos.setPayUrl(obj);
            pos.setPayType("2");
            posOrderService.saveOrUpdate(pos);
            return success(MessageUtils.message("no.order.create.success"), obj);
        }
    }


    //查询支付订单
    @SneakyThrows
    @Anonymous
    @RequestMapping(value = "/getVNPayorder", method = {RequestMethod.POST})
    public AjaxResult getVNPayorder(@RequestBody PayResponse payResponse, HttpServletRequest request) {

        IpUtils ipUtils = new IpUtils();
        String ip = ipUtils.getIpAddr(request);
        Md5Pay md5Pay = new Md5Pay();
        String obj = md5Pay.getPay(payResponse, ip);
        JSONObject json = JSONUtil.toBean(obj, JSONObject.class);
        return success(json);
    }

    //（售后退款）退款请求
    @SneakyThrows
    @Anonymous
    @Auth
    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
    @RequestMapping(value = "/VNtuikuan", method = {RequestMethod.GET, RequestMethod.POST})
    public AjaxResult VNtuikuan(@RequestHeader String token, @RequestBody PayVN payVN, HttpServletRequest request) {

        JwtUtil jwtUtil = new JwtUtil();
        IpUtils ipUtils = new IpUtils();
        String ip = ipUtils.getIpAddr(request);
        String id = jwtUtil.getusid(token);
        InfoUser user = infoUserService.getById(id);
        System.out.println("退款用户信息：" + user.getPhone());
//            DateUtil dateUtil = new DateUtil();
        Md5Pay md5Pay = new Md5Pay();
        payVN.setIpaddr(ip);
        payVN.setUser(user.getPhone());
        String obj = md5Pay.doPost(payVN);
        JSONObject json = JSONUtil.toBean(obj, JSONObject.class);
        QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
        wrapper.eq("dd_id", payVN.getOrder_id());
        wrapper.eq("user_id", id);
        wrapper.eq("type", "3");
        wrapper.eq("state", "0");
        UserBilling billing = userBillingService.getOne(wrapper);
        System.out.println("退款结果代码：" + json.get("vnp_ResponseCode"));
        if (json.get("vnp_ResponseCode").equals("00")) {
            if (payVN.getTrantype().equals("02")) {
                billing.setState("2");
                userBillingService.saveOrUpdate(billing);
            } else {
                UserBilling usbi = new UserBilling();
                usbi.setUserId(Long.valueOf(id));
                usbi.setType("3");
                usbi.setDdId(payVN.getOrder_id());
                usbi.setAmount(Double.valueOf(payVN.getAmount()));
                usbi.setMdId(billing.getMdId());
                usbi.setIllustrate(payVN.getIllustrate());
                usbi.setState("1");
                userBillingService.saveOrUpdate(usbi);
            }
            return success(json);
        } else {
            return success(json);
        }
    }






    //接收IPN支付回调
    @Anonymous
    @RequestMapping(value = "/payipn", method = {RequestMethod.GET, RequestMethod.POST})
    public JSONObject payipn(HttpServletRequest request) {
        JSONObject org = new JSONObject();
        IpUtils ipUtils = new IpUtils();
        String ip = ipUtils.getIpAddr(request);
        Map map = new HashMap();
        Enumeration paramNames = request.getParameterNames();
        while (paramNames.hasMoreElements()) {
            String paramName = (String) paramNames.nextElement();
            String[] paramValues = request.getParameterValues(paramName);
            if (paramValues.length == 1) {
                String paramValue = paramValues[0];
                if (paramValue.length() != 0) {
                    map.put(paramName, paramValue);
                }
            }
        }
        System.out.println("IP : " + ip);
        IpnLog log = new IpnLog();
        log.setIp(ip);
        log.setIpnLog(map.toString());
        ipnLogService.insertIpnLog(log);
        if (ip.equals("1.34.167.110") || ip.equals("113.160.92.202") || ip.equals("113.52.45.78") || ip.equals("116.97.245.130") || ip.equals("42,118,107.252") || ip.equals("113.20.97.250") || ip.equals("203.171.19.146") || ip.equals("127.0.0.1")) {
            String vnp_SecureHash = map.get("vnp_SecureHash").toString();
            if (map.containsKey("vnp_SecureHashType")) {
                map.remove("vnp_SecureHashType");
            }
            if (map.containsKey("vnp_SecureHash")) {
                map.remove("vnp_SecureHash");
            }
            String signValue = VNPay.hashAllFields(map);
            PayPush push = new PayPush();
            String orderid = map.get("vnp_TxnRef").toString().substring(0, 2);
            System.out.println("回调信息" + map);
            System.out.println("订单号：" + map.get("vnp_TxnRef").toString());
            System.out.println("远程取回vnp_SecureHash：" + vnp_SecureHash);
            System.out.println("本地计算vnp_SecureHash：" + signValue);
            if (signValue.equals(vnp_SecureHash)) {
                if ("00".equals(request.getParameter("vnp_ResponseCode"))) {
                    if (orderid.equals("CZ")) {
                        QueryWrapper<UserBilling> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("dd_id", map.get("vnp_TxnRef").toString());
                        UserBilling billing = userBillingService.getOne(queryWrapper);
                        if (billing == null) {
                            org.put("RspCode", "01");
                            org.put("Message", "Order not Found");
                        } else {

                            InfoUser user = infoUserService.getById(billing.getUserId());
                            String amount = map.get("vnp_Amount").toString();
                            Double oramout = billing.getAmount() * 100;
                            DecimalFormat df = new DecimalFormat("0.##");
                            String s = df.format(oramout);
                            System.out.println("金额对比：" + amount + "/" + s);
                            if (amount.equals(s)) {
                                if (billing.getState().equals("3")) {
                                    UserBilling usbi = new UserBilling();
                                    usbi.setId(billing.getId());
                                    usbi.setState(String.valueOf(0));
                                    userBillingService.saveOrUpdate(usbi);
                                    Map<String, Object> orderMap=OrderPushBodyDto.getMap(billing.getDdId(),billing.getState(),-1,2);
                                    String json = OrderPushBodyDto.margeMapGetJsonString(orderMap,map);
                                    if (user.getUserType().equals("1")) {
//                                        push.shpush(user.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.recharge.success"), String.valueOf(map));

                                        pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.recharge.success"), json);
                                    } else {
                                        push.qspush(user.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.recharge.success"),json);
                                        pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.recharge.success"), json);
                                    }
                                } else {
                                    org.put("RspCode", "02");
                                    org.put("Message", "Order already confirmed");
                                }
                            } else {
                                org.put("RspCode", "04");

                            }
                        }
                    } else
                    {
                        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("dd_id", map.get("vnp_TxnRef").toString());
                        PosOrder posOrder = posOrderService.getOne(queryWrapper);
                        if (posOrder == null) {
                            System.out.println("订单不存在============");
                            org.put("RspCode", "01");
                            org.put("Message", "Order not Found");
                        } else {
                            InfoUser user = infoUserService.getById(posOrder.getUserId());
                            InfoUser shanghu = infoUserService.getById(posOrder.getShId());
                            String amount = map.get("vnp_Amount").toString();
                            int oramout = posOrder.getAmount() * 100;
//                            DecimalFormat df = new DecimalFormat("0.##");
                            String s = String.valueOf(oramout);
                            System.out.println("金额对比：" + amount + "/" + s);
                            if (amount.equals(s)) {
                                System.out.println("订单状态：" + posOrder.getState());
                                if (posOrder.getState() == 0) {
                                    PosOrder order = new PosOrder();
                                    order.setId(posOrder.getId());
                                    order.setState(1L);
                                    posOrderService.saveOrUpdate(order);
                                    QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
                                    wrapper.eq("dd_id", posOrder.getDdId());
                                    wrapper.eq("type", "3");
                                    wrapper.eq("state", "3");
                                    UserBilling billing = userBillingService.getOne(wrapper);
                                    if (billing != null) {
                                        billing.setState("0");
                                        billing.setAmount(Double.valueOf(amount));
                                        billing.setIllustrate("VNPayConsumer payment");
                                        billing.setPaymentMethod("VNPay");
                                        userBillingService.saveOrUpdate(billing);
                                    }
                                    Map<String, Object> orderMap=OrderPushBodyDto.getMap(String.valueOf(posOrder.getDdId()),"1",0,1);
                                    String json = OrderPushBodyDto.margeMapGetJsonString(orderMap,map);
                                    System.out.println("======================================推送支付结果");
                                    push.apppush(user.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.success"), json);
                                    pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.success"), json);
                                    push.shpush(shanghu.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), json);
                                    pushEventService.PublisherEvent(shanghu.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), json);
                                    sendAcceptRiderPush(posOrder, push, riderPositionMapper,OrderPushBodyDto.getJson(String.valueOf(posOrder.getDdId()), String.valueOf(order.getState()),1));
                                    org.put("RspCode", "00");
                                    org.put("Message", "Confirm Success");
                                } else {
                                    org.put("RspCode", "02");
                                    org.put("Message", "Order already confirmed");
                                }
                            } else {
                                org.put("RspCode", "04");
                                org.put("Message", "Invalid amount");
                            }
                        }
                    }
                } else {
                    if (orderid.equals("CZ")) {
                        QueryWrapper<UserBilling> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("dd_id", map.get("vnp_TxnRef").toString());
                        UserBilling billing = userBillingService.getOne(queryWrapper);
                        InfoUser user = infoUserService.getById(billing.getUserId());
                        Map<String, Object> orderMap=OrderPushBodyDto.getMap(billing.getDdId(),billing.getState(),-1,2);
                        String json = OrderPushBodyDto.margeMapGetJsonString(orderMap,map);
                        push.apppush(user.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.fail"), String.valueOf(map));
                        pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.fail"), json);
                    } else {
                        QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("dd_id", map.get("vnp_TxnRef").toString());
                        PosOrder posOrder = posOrderService.getOne(queryWrapper);
                        Map<String, Object> orderMap=OrderPushBodyDto.getMap(String.valueOf(posOrder.getDdId()),"0",-1,1);
                        String json = OrderPushBodyDto.margeMapGetJsonString(orderMap,map);
                        InfoUser user = infoUserService.getById(posOrder.getUserId());
                        push.apppush(user.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.fail"),json);
                        pushEventService.PublisherEvent(user.getUserId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.payment.fail"), json);
                    }
                    org.put("RspCode", "00");
                    org.put("Message", "Confirm Success");
                }

            } else {
                // Sai checksum
                System.out.println("h값不一至===================");
                org.put("RspCode", "97");
                org.put("Message", "Invalid Checksum");
            }
            return org;
        } else {
            org.put("RspCode", "99");
            org.put("Message", "Illegal IP access");
            return org;
        }

    }

    /**
     * 推送可接单骑手
     *
     * @param order
     * @param push
     */
    @Async(value = "threadPoolTaskExecutor")
    public void sendAcceptRiderPush(PosOrder order, PayPush push, RiderPositionMapper riderPositionMapper,String body) {
        // type=0外送,CollectPayment=1 到付
        if(order.getState()!=0){
            return;
        }
        List<RiderPosition> riders = riderPositionMapper.getAcceptRiderList(order.getLongitude(), order.getLatitude(), 20);

        List<RiderPosition> validRiders = riders.stream()
                .filter(x -> x.getCid() != null && !x.getCid().isEmpty())
                .collect(Collectors.toList());
        int taskCount = validRiders.size();
        CountDownLatch latch = new CountDownLatch(taskCount);
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

        for (int i = 0; i < taskCount; i++) {
            RiderPosition rider = validRiders.get(i);
            final int index = i;

            scheduler.schedule(() -> {
                try {
                    System.out.println("========== 可接单骑手推送 ==========cid:" + rider.getCid() + "riderId:" + rider.getRiderId() + ",mapJson:" + body);
                    push.qspush(rider.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), body
                    );
                    pushEventService.PublisherEvent(rider.getRiderId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), body
                    );
                } catch (Exception e) {
                    log.error("推送骑手异常", e);
                } finally {
                    // 无论成功与否，都减少计数
                    latch.countDown();
                }
            }, i * 2L, TimeUnit.SECONDS);
        }

        // 另启一个线程等待所有任务完成，然后关闭调度器
        scheduler.submit(() -> {
            try {
                // 等待所有任务完成（超时时间设置为总间隔时间+额外缓冲）
                long timeout = (taskCount * 2L) + 10; // 额外10秒缓冲
                if (latch.await(timeout, TimeUnit.SECONDS)) {
                    log.info("所有骑手推送完成");
                } else {
                    log.warn("骑手推送超时，仍有{}个任务未完成", latch.getCount());
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                // 关闭调度器
                scheduler.shutdown();
            }
        });


//        if (order.getType() == 0) {
//            List<RiderPosition> riders = riderPositionMapper.getAcceptRiderList(order.getLongitude(), order.getLatitude(), 20);
//            riders.stream().filter(x -> x.getCid() != null && !x.getCid().isEmpty()).forEach(x -> {
//
//                System.out.println("========== 可接单骑手推送 ==========cid:" + x.getCid() + "riderId:" + x.getRiderId() + ",mapJson:" + body);
//                push.qspush(x.getCid(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), body
//                );
//                pushEventService.PublisherEvent(x.getRiderId(), MessageUtils.message("no.message.push.message"), MessageUtils.message("no.message.push.new.order"), body
//                );
//
//                try {
//                    Thread.sleep(2000);
//                } catch (InterruptedException e) {
//                    log.error("线程睡眠异常", e);
//                }
//
//            });
//        }
    }

    @Anonymous
    @RequestMapping(value = "/payJson", method = {RequestMethod.GET, RequestMethod.POST})
    public AjaxResult payJson(HttpServletRequest request) {
        Map map = new HashMap();
        Enumeration paramNames = request.getParameterNames();
        while (paramNames.hasMoreElements()) {
            String paramName = (String) paramNames.nextElement();
            String[] paramValues = request.getParameterValues(paramName);
            if (paramValues.length == 1) {
                String paramValue = paramValues[0];
                if (paramValue.length() != 0) {
                    map.put(paramName, paramValue);
                }
            }
        }
        return success("success", "");
    }


}
