package com.wteam.framework.modules.pay.serviceimpl.handler;


import   cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.egzosn.pay.common.api.PayMessageHandler;
import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.common.bean.PayMessage;
import com.egzosn.pay.common.bean.PayOutMessage;
import com.egzosn.pay.common.exception.PayErrorException;

import com.wteam.framework.common.enums.CardTypeEnum;
import com.wteam.framework.common.enums.OrderStatus;
import com.wteam.framework.common.enums.OrderStatusEnum;

import com.wteam.framework.common.exception.ServiceException;

import com.wteam.framework.modules.book.entity.Card;
import com.wteam.framework.modules.book.entity.OrderInfo;
import com.wteam.framework.modules.book.mapper.CardMapper;
import com.wteam.framework.modules.book.mapper.OrderInfoMapper;
import com.wteam.framework.modules.book.service.CardService;

import com.wteam.framework.modules.book.service.OrderInfoService;
import com.wteam.framework.modules.card.entity.CbCardAdmin;
import com.wteam.framework.modules.card.mapper.CardAdminMapper;
import com.wteam.framework.modules.hardware.ApiCallerUtil;
import com.wteam.framework.modules.user.entity.User;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;

import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Map;


@Slf4j
@Component
public class MyPayMessageHandler implements PayMessageHandler {

    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private CardService cardService;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private CardMapper cardMapper;
    @Autowired
    private CardAdminMapper cardAdminMapper;

    /**
     * 重写这个接口处理支付业务请求
     *
     * @param payMessage 支付消息
     * @param context    上下文，如果handler或interceptor之间有信息要传递，可以用这个
     * @param payService 支付服务
     * @throws PayErrorException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PayOutMessage handle(PayMessage payMessage, Map context, PayService payService) throws PayErrorException {
        try {
            // 输入验证
            if (payMessage == null || payMessage.getPayMessage() == null) {
                throw new IllegalArgumentException("Invalid payMessage");
            }

            // 处理支付逻辑
            String outTradeNo = payMessage.getOutTradeNo(); // 获取交易订单号
            Number totalFee = payMessage.getTotalFee(); // 获取总费用（可能是一个数字）
            String subject = payMessage.getSubject(); // 获取交易主题
            String payType = payMessage.getPayType(); // 获取支付类型
            String transactionType = payMessage.getTransactionType();  // 获取交易类型
            log.info("此时的支付订单号为{}", outTradeNo);
            log.info("此时的支付总费用为{}", totalFee);
            log.info("此时的支付交易主题为{}", subject);
            log.info("此时的支付支付类型为{}", payType);
            log.info("获取交易类型为{}", transactionType);

            // 根据订单ID查询订单信息
            OrderInfo orderInfo = orderInfoMapper.selectById(outTradeNo);
            log.info("此时的order信息为{}", orderInfo);

            //如果是超时的情况，单独考虑
            Double overPrice = orderInfo.getOverPrice();
            if (overPrice != null && overPrice > 0) {
                // overPrice 大于 0 表示超时，需要处理超时情况
                // 在这里可以执行超时处理的逻辑
                //生成一个只能通过一次的二维码
                // 获取当前日期
                LocalDate currentDate = LocalDate.now();
                // 格式化日期为字符串
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
                String formattedDate = currentDate.format(formatter);
                String data = "pxo_" + formattedDate + "_" + orderInfo.getUserId() + "_" + orderInfo.getId() + "_00";
                log.info("此时生成的二维码为：{} ", data);
                //更新数据库里面此时二维码信息
                orderInfo.setQrCode(data);
                orderInfoMapper.updateById(orderInfo);
                // 注册二维码
                // 接口地址和参数
                String apiUrl = "https://xiaofeng.pankzone.com/api/openapi/reg_access_qcode.x";
                String mac = "863569068849199";
                String tk = ApiCallerUtil.callApi();
                log.info("此时获取到的token为：{} ", tk);

                //调用hutool接口注册二维码信息
                HttpResponse response = HttpRequest.post(apiUrl).form("mac", mac).form("tk", tk).form("qcodetxt", data).form("enablecount", 1).execute();
                //获取响应结果
                String body = response.body();
                // 处理返回结果
                JSONObject json = new JSONObject(body);
                int code = json.getInt("code");
                String qcodetxt = json.getStr("qcodetxt");
                log.info("此时返回的qcodetxt为：{}", qcodetxt);
                String desc = json.getStr("desc");
                log.info("此时返回的desc为：{}", desc);
                //对响应结果处理
                if (code != 0) {
                    throw new ServiceException("硬件回调url设置接口异常！");
                }
                log.info("此时接口响应数据为：{} (不要记录敏感信息在日志中)", body);
            }

            if (orderInfo != null) {

                //这里根据订单的类型生成不同的二维码注销
                String orderType = orderInfo.getOrderType();
                /**
                 * 租场订单-->生成的二维码有时间限制，前5后15，进出次数不限制
                 * 门票订单-->生成的二维码没有时间限制，任何时候来都可以，但是进出限制2次，一出一进就结束
                 * 计时订单-->生成的二维码没有时间限制，也是先支付一个小时的钱，支付成功后修改订单状态！
                 * 月卡订单-->生成的二维码截至时间为月卡结束时间，进出没有限制
                 * 储值卡订单-->直接完成支付业务逻辑即可
                 */

                switch (orderType) {
                    case "RENTAL":
                        // 处理租场订单类型的支付逻辑
                        return RentalOrder(orderInfo);
                    case "TICKET":
                        // 处理门票订单类型的支付逻辑
                        return TicketOrder(orderInfo);
                    case "TIMER":
                        // 处理计时订单类型的支付逻辑
                        return TimerOrder(orderInfo);
                    case "MONTHLY":
                        // 处理月卡订单类型的支付逻辑
                        return MonthlyOrder(orderInfo);
                    case "STORED_VALUE":
                        // 处理卡片订单类型的支付逻辑
                        return CardOrder(orderInfo);
                    default:
                        // 处理未知订单类型的情况
                        break;
                }
            }
        } catch (Exception e) {
            log.info("此时的异常为：{}", e.getMessage());
        }
        return PayOutMessage.TEXT().content("fail").build();
    }

    /**
     * 购买卡之后的支付回调
     *
     * @param orderInfo
     * @return
     */
    private PayOutMessage CardOrder(OrderInfo orderInfo) {
        //修改订单状态
        orderInfo.setPaymentMethods("WECHAT");
        orderInfo.setOrderState(String.valueOf(OrderStatus.PAYMENT_SUCCESSFUL));
        orderInfoMapper.updateById(orderInfo);
        // 格式化日期为字符串
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String formattedDate = currentDate.format(formatter);
        //微信购买卡之后支付回调信息
        Integer cardId = orderInfo.getCardId();
        log.info("此时卡id为{}", cardId);
        //获取卡信息
        Card card = cardMapper.selectById(cardId);
        log.info("此时卡信息为{}", card);
        String userId = card.getUserId();
        log.info("此时userId信息为{}", userId);
        if (userId != null && !userId.isEmpty()) {
            try {
                // 这种情况就证明此时该用户进行的是储值卡充值的操作
                Double orderPrice = orderInfo.getOrderPrice();
                card.setCurrentBalance(orderPrice);
                cardMapper.updateById(card);
                return PayOutMessage.TEXT().content("success").build();
            } catch (Exception e) {
                // 处理异常，可以记录日志或返回适当的错误信息
                e.printStackTrace(); // 这里仅作示例，实际中请根据需求处理异常
                return PayOutMessage.TEXT().content("充值失败，请联系客服").build();
            }
        }
        CbCardAdmin cbCardAdmin = cardAdminMapper.selectById(cardId);
        Card cardUser = new Card();
        //获取余额
        Integer faceValue = cbCardAdmin.getFaceValue();
        cardUser.setCardName(cbCardAdmin.getCardName());
        cardUser.setUserId(orderInfo.getUserId());
        cardUser.setFaceValue(faceValue);
        cardUser.setCreateTime(new Date());
        log.info("当前的余额为:{}", faceValue);
        cardUser.setCardType(cbCardAdmin.getCardType());
        cardUser.setDays(cbCardAdmin.getDays());
        cardUser.setStartDate(formattedDate);
        cardUser.setCurrentBalance(Double.valueOf(faceValue));
        cardUser.setUserId(orderInfo.getUserId());
        log.info("此时获取出来的userId为:{}", orderInfo.getUserId());
        cardUser.setDiscountValue(cbCardAdmin.getDiscountValue());
        Integer days = card.getDays();
        // 将天数添加到日期
        LocalDate newDate = currentDate.plusDays(days);
        // 将新日期格式化为字符串
        String newFormattedDate = newDate.format(formatter);
        cardUser.setEndDate(newFormattedDate);
        log.info("此时的enddate为:{}", newFormattedDate);
        log.info("此时的cardUser信息为：{}", cardUser);
        boolean save = cardService.save(cardUser);
        if (save) {
            return PayOutMessage.TEXT().content("success").build();
        }
        return PayOutMessage.TEXT().content("fail").build();
    }

    private PayOutMessage MonthlyOrder(OrderInfo orderInfo) {
        // 修改订单状态为已支付
        orderInfo.setOrderState(String.valueOf(OrderStatus.PAYMENT_SUCCESSFUL));
        log.info("此时的OrderState信息为{}", orderInfo.getOrderState());

        // 修改订单支付方式
        orderInfo.setPaymentMethods("WECHAT");
        log.info("此时的PaymentMethods信息为{}", orderInfo.getPaymentMethods());

        orderInfoMapper.updateById(orderInfo);

        //格式转化一下
        String id = orderInfo.getId();
        log.info("转化之后的id为：{}", id);
        long l = Long.parseLong(id);
        log.info("转化之后的id为：{}", l);

        //获取卡信息
        Integer cardId = orderInfo.getCardId();
        log.info("此时的卡id为:{}", cardId);
        CbCardAdmin card = cardAdminMapper.selectById(cardId);
        log.info("此时的卡信息为:{}", card);
        String endDate = card.getEndDate();
        log.info("此时的结束时间为{}", endDate);

        // 格式化日期为字符串
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String formattedDate = currentDate.format(formatter);

        //创建卡信息
        Card cardUser = new Card();
        Integer faceValue = card.getFaceValue();
        cardUser.setCardName(card.getCardName());
        cardUser.setUserId(orderInfo.getUserId());
        cardUser.setFaceValue(faceValue);
        cardUser.setCreateTime(new Date());
        log.info("当前的余额为:{}", faceValue);
        cardUser.setCardType(card.getCardType());
        cardUser.setDays(card.getDays());
        cardUser.setStartDate(formattedDate);
        cardUser.setCurrentBalance(Double.valueOf(faceValue));
        cardUser.setUserId(orderInfo.getUserId());
        cardUser.setDiscountValue(card.getDiscountValue());
        Integer days = card.getDays();
        // 将天数添加到日期
        LocalDate newDate = currentDate.plusDays(days);
        // 将新日期格式化为字符串
        String newFormattedDate = newDate.format(formatter);
        cardUser.setEndDate(newFormattedDate);
        log.info("此时的enddate为:{}", newFormattedDate);
        log.info("此时的cardUser信息为：{}", cardUser);
        cardService.save(cardUser);


        //此时的结束时间为卡二维码截至时间
        try {
            // 获取当前日期
            LocalDate currentDate1 = LocalDate.now();
            log.info("此时的时间为{}", currentDate);

            // 创建 SimpleDateFormat 对象，指定日期格式
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            // 将日期字符串解析为 Date 对象
            Date date = sdf.parse(endDate);
            log.info("此时的date为:{}", date);

            // 将 Date 对象转化为秒级时间戳
            // 除以1000以获取秒级时间戳
            long timestamp = date.getTime() / 1000;

            // 格式化日期为字符串
            DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyyMMdd");
            String formattedDate1 = currentDate1.format(formatter1);
            log.info("此时格式化的日期为:{}", formattedDate);

            String data = "pxo_" + formattedDate1 + "_" + orderInfo.getUserId() + "_" + l + "_00";
            log.info("此时生成的二维码为：{} ", data);
            orderInfo.setQrCode(data);
            orderInfoService.updateById(orderInfo);

            // 注册二维码
            // 接口地址和参数
            String apiUrl = "https://xiaofeng.pankzone.com/api/openapi/reg_access_qcode.x";
            String mac = "863569068849199";
            String tk = ApiCallerUtil.callApi();
            log.info("此时获取到的token为：{} ", tk);

            //使用hutool调用接口
            HttpResponse response = HttpRequest.post(apiUrl).form("mac", mac).form("tk", tk).form("qcodetxt", data).form("enabletime", timestamp).form("enablecount", 5000).execute();
            //获取响应结果
            String body = response.body();
            // 处理返回结果
            JSONObject json = new JSONObject(body);
            int code = json.getInt("code");
            String qcodetxt = json.getStr("qcodetxt");
            log.info("此时返回的qcodetxt为：{}", qcodetxt);
            String desc = json.getStr("desc");
            log.info("此时返回的desc为：{}", desc);
            //对响应结果处理
            if (code != 0) {
                throw new ServiceException("硬件回调url设置接口异常！");
            }
            log.info("此时接口响应数据为：{} (不要记录敏感信息在日志中)", body);
        } catch (ParseException e) {
            log.info("此时的异常为：{}", e.getMessage());
        }
        // 返回适当的PayOutMessage
        return PayOutMessage.TEXT().

                content("success").

                build();

    }


    private PayOutMessage TimerOrder(OrderInfo orderInfo) {
        // 修改订单状态为已支付
        orderInfo.setOrderState(String.valueOf(OrderStatus.PAYMENT_SUCCESSFUL));
        log.info("此时的OrderState信息为{}", orderInfo.getOrderState());

        // 修改订单支付方式
        orderInfo.setPaymentMethods("WECHAT");
        log.info("此时的PaymentMethods信息为{}", orderInfo.getPaymentMethods());

        orderInfoMapper.updateById(orderInfo);

        //设置进出时间
        orderInfo.setStartTime(new Date());

        //格式转化一下
        String id = orderInfo.getId();
        log.info("转化之后的id为：", id);
        long l = Long.parseLong(id);
        log.info("转化之后的id为：", l);

        int i = orderInfoMapper.updateById(orderInfo);

        if (i > 0) {
            return PayOutMessage.TEXT().content("success").build();
        }
        // 返回适当的PayOutMessage
        return PayOutMessage.TEXT().content("fail").build();
    }


    private PayOutMessage TicketOrder(OrderInfo orderInfo) {
        // 修改订单状态为已支付
        orderInfo.setOrderState(String.valueOf(OrderStatusEnum.WAITING_TO_USE));
        log.info("此时的OrderState信息为{}", orderInfo.getOrderState());

        // 修改订单支付方式
        orderInfo.setPaymentMethods("WECHAT");
        log.info("此时的PaymentMethods信息为{}", orderInfo.getPaymentMethods());

        orderInfoMapper.updateById(orderInfo);

        // 获取当前日期
        LocalDate currentDate = LocalDate.now();

        //格式转化一下
        String id = orderInfo.getId();
        log.info("转化之后的id为：", id);
        long l = Long.parseLong(id);
        log.info("转化之后的id为：", l);

        //创建卡信息
        Card cardUser = new Card();
        cardUser.setCardType(String.valueOf(CardTypeEnum.TICKET));
        cardUser.setDiscountValue(null);
        cardUser.setUserId(orderInfo.getUserId());
        cardUser.setCreateTime(new Date());
        cardUser.setCardName("篮球次卡");
        cardService.save(cardUser);


        // 格式化日期为字符串
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String formattedDate = currentDate.format(formatter);
        String data = "pxo_" + formattedDate + "_" + orderInfo.getUserId() + "_" + l + "_00";
        log.info("此时生成的二维码为：{} ", data);

        // 保存入数据库
        orderInfo.setQrCode(data);
        log.info("此时的orderInfo为:{}", orderInfo);
        boolean b = orderInfoService.updateById(orderInfo);

        if (b) {
            // 接口地址和参数
            String apiUrl = "https://xiaofeng.pankzone.com/api/openapi/reg_access_qcode.x";
            String mac = "863569068849199";
            String tk = ApiCallerUtil.callApi();
            log.info("此时获取到的token为：{} ", tk);
            //使用hutool调用接口
            HttpResponse response = HttpRequest.post(apiUrl).form("mac", mac).form("tk", tk).form("qcodetxt", data).form("enablecount", 2).execute();
            //获取响应结果
            String body = response.body();
            // 处理返回结果
            JSONObject json = new JSONObject(body);
            int code = json.getInt("code");
            String qcodetxt = json.getStr("qcodetxt");
            log.info("此时返回的qcodetxt为：{}", qcodetxt);
            String desc = json.getStr("desc");
            log.info("此时返回的desc为：{}", desc);
            //对响应结果处理
            if (code != 0) {
                throw new ServiceException("硬件回调url设置接口异常！");
            }
            log.info("此时接口响应数据为：{} ", body);
        }
        // 返回适当的PayOutMessage
        return PayOutMessage.TEXT().content("success").build();
    }


    private PayOutMessage RentalOrder(OrderInfo orderInfo) {
        // 修改订单状态为已支付
        orderInfo.setOrderState(String.valueOf(OrderStatusEnum.WAITING_TO_USE));
        log.info("此时的OrderState信息为{}", orderInfo.getOrderState());

        // 修改订单支付方式
        orderInfo.setPaymentMethods("WECHAT");
        log.info("此时的PaymentMethods信息为{}", orderInfo.getPaymentMethods());

        orderInfoMapper.updateById(orderInfo);

        // 获取当前日期
        LocalDate currentDate = LocalDate.now();

        //格式转化一下
        String id = orderInfo.getId();
        log.info("转化之后的id为：{}", id);
        long l = Long.parseLong(id);
        log.info("转化之后的id为：{}", l);

        // 格式化日期为字符串
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String formattedDate = currentDate.format(formatter);
        String data = "pxo_" + formattedDate + "_" + orderInfo.getUserId() + "_" + l + "_00";
        log.info("此时生成的二维码为：{} ", data);

        // 保存入数据库
        orderInfo.setQrCode(data);
        int save = orderInfoMapper.updateById(orderInfo);

        if (save > 0) {
            // 接口地址和参数
            String apiUrl = "https://xiaofeng.pankzone.com/api/openapi/reg_access_qcode.x";
            String mac = "863569068849199";
            String tk = ApiCallerUtil.callApi();
            log.info("此时获取到的token为：{} ", tk);
            //获取订单开始和结束时间
            Date orderSt = orderInfo.getOrderSt();
            Date orderEd = orderInfo.getOrderEd();
            // 转化为时间戳
            // 前5后15
            // 获取当前时间的时间戳（毫秒级）
            long currentTimeMillis = System.currentTimeMillis();

            // 将订单开始时间前推5分钟并转换为时间戳
            long orderStTimestamp = orderSt.getTime() - (5 * 60 * 1000);

            // 将订单结束时间后推10分钟并转换为时间戳
            long orderEdTimestamp = orderEd.getTime() + (10 * 60 * 1000);

            // 如果需要确保不早于当前时间，可以添加以下逻辑
            orderStTimestamp = Math.max(orderStTimestamp, currentTimeMillis);
            orderEdTimestamp = Math.max(orderEdTimestamp, currentTimeMillis);
            //使用hutool调用接口
            HttpResponse response = HttpRequest.post(apiUrl).form("mac", mac).form("tk", tk).form("qcodetxt", data).form("starttime", orderStTimestamp).form("enabletime", orderEdTimestamp).form("enablecount", 100).execute();
            //获取响应结果
            String body = response.body();
            // 处理返回结果
            JSONObject json = new JSONObject(body);
            int code = json.getInt("code");
            String qcodetxt = json.getStr("qcodetxt");
            log.info("此时返回的qcodetxt为：{}", qcodetxt);
            String desc = json.getStr("desc");
            log.info("此时返回的desc为：{}", desc);
            //对响应结果处理
            if (code != 0) {
                throw new ServiceException("硬件回调url设置接口异常！");
            }
            log.info("此时接口响应数据为：{} (不要记录敏感信息在日志中)", body);
        }
        // 返回适当的PayOutMessage
        return PayOutMessage.TEXT().content("success").build();
    }
}
