package com.wteam.framework.modules.book.service.impl;

import cn.hutool.core.util.ObjectUtil;
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.Jeepay;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.model.PayOrderCreateReqModel;
import com.jeequan.jeepay.request.PayOrderCreateRequest;
import com.jeequan.jeepay.response.PayOrderCreateResponse;
import com.wteam.framework.common.enums.*;
import com.wteam.framework.common.exception.ServiceException;
import com.wteam.framework.common.security.AuthUser;
import com.wteam.framework.common.security.context.UserContext;
import com.wteam.framework.common.utils.BeanUtil;
import com.wteam.framework.common.vo.ResultMessage;
import com.wteam.framework.modules.book.entity.Card;
import com.wteam.framework.modules.book.entity.OrderInfo;
import com.wteam.framework.modules.book.entity.Store;
import com.wteam.framework.modules.book.entity.dto.OrderCardReq;
import com.wteam.framework.modules.book.entity.dto.StoredCardDto;
import com.wteam.framework.modules.book.entity.vo.CardVo;
import com.wteam.framework.modules.book.entity.vo.OrderVo;
import com.wteam.framework.modules.book.mapper.CardMapper;
import com.wteam.framework.modules.book.mapper.OrderInfoMapper;
import com.wteam.framework.modules.book.mapper.StoreMapper;
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.pay.serviceimpl.CashierSupport;
import com.wteam.framework.modules.system.entity.dto.WechatPaymentSetting;
import com.wteam.framework.modules.system.service.SettingService;
import com.wteam.framework.modules.user.entity.User;
import com.wteam.framework.modules.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.wteam.framework.modules.book.service.impl.OrderInfoServiceImpl.getWechatPaymentSetting;

/**
 * (Card)表服务实现类
 *
 * @author doncic
 * @since 2023-09-18 19:19:57
 */
@Slf4j
@Service("cardService")
public class CardServiceImpl extends ServiceImpl<CardMapper, Card> implements CardService {

    @Autowired
    private CardMapper cardMapper;
    @Autowired
    private StoreMapper storeMapper;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private SettingService settingService;
    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private CardService cardService;
    @Autowired
    private CashierSupport cashierSupport;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private CardAdminMapper cardAdminMapper;

    @Override
    public ResultMessage showCard(@NotNull Long id, CardTypeEnum cardTypeEnum) {
        //根据id查到此店名称
        Store store = storeMapper.selectById(id);
        if (ObjectUtil.isNull(store)) {
            return ResultUtil.error(ResultCode.ENTITY_NULL);
        }
        String storeName = store.getStoreName();
        //创建lambdaQueryWrapper对象
        LambdaQueryWrapper<Card> queryWrapper = new LambdaQueryWrapper<>();
        //传入id和card表里面storeId比对
        queryWrapper.eq(Card::getStoreId, id);
        //获取cards集合
        List<Card> cards = cardMapper.selectList(queryWrapper);
        if (ObjectUtil.isNull(cards)) {
            return ResultUtil.error(ResultCode.ENTITY_NULL);
        }
        log.info("此时获取到的卡有:{}", cards);
        String cardType = String.valueOf(cardTypeEnum);
        List<Card> cardList = cards.stream().filter(card -> Objects.equals(card.getCardType(), cardType)).collect(Collectors.<Card>toList());
        log.info("此时获取到的卡是:{}", cardList);
        StoredCardDto storedCardDto = new StoredCardDto(cardList, storeName);
        return ResultUtil.data(storedCardDto);
    }

    @Override
    public ResultMessage showCardDetails(@NotNull Long id) {
        //查找卡信息
        CbCardAdmin card = cardAdminMapper.selectById(id);
        if (ObjectUtil.isNull(card)) {
            throw new ServiceException("查不到对应卡信息");
        }
        CardVo cardVo = new CardVo();
        //bean拷贝
        BeanUtil.copyProperties(card, cardVo);
        return ResultUtil.data(cardVo);
    }

    @Override
    public ResultMessage buyCard(@NotNull String accessToken, @NotNull String orderId, Long cardId) {
        // 校验token
        AuthUser authUser = UserContext.getAuthUser(accessToken);
        assert authUser != null;
        String id = authUser.getId();
        log.info("此时的userId信息为：{}", id);

        // 先查询卡是否存在
        Card card = cardMapper.selectById(cardId);
        log.info("此时的卡信息为：{}", card);

        if (ObjectUtil.isNull(card)) {
            throw new ServiceException("查不到对应卡信息");
        }

        //查询订单信息
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        log.info("此时的订单信息为：{}", orderInfo);

        if (ObjectUtil.isNotNull(orderInfo)) {
            // 调用微信支付的接口
            String paymentEndpointUrl = "http://139.9.38.185:8889/v1/payment/pay/WECHAT/JSAPI?" + "sn=" + orderId;
            // 构建GET请求
            HttpRequest request = HttpRequest.get(paymentEndpointUrl);
            // 发送请求并获取响应
            HttpResponse response = request.execute();
            // 处理响应
            if (response.isOk()) {
                String responseBody = response.body();
                log.info("此时的响应信息为：{}", responseBody);// 保存卡信息
                Card cardUser = new Card();
                cardUser.setCardType(card.getCardType());
                cardUser.setDays(card.getDays());
                cardUser.setStartDate(String.valueOf(new Date()));
                cardUser.setEndDate(cardUser.getStartDate() + cardUser.getDays());
                log.info("此时的cardUser信息为：{}", cardUser);
                cardService.save(cardUser);
                // 处理成功响应

            } else {
                // 处理错误响应
                System.err.println("Error Response: " + response.getStatus() + " " + response.body());
            }
        }
        return ResultUtil.error(ResultCode.ORDER_NOT_EXIST);
    }

    @Override
    public ResultMessage chargeCard(String accessToken, Long id) {
        try {
            // 校验token
            AuthUser authUser = UserContext.getAuthUser(accessToken);
            assert authUser != null;
            Long userId = Long.valueOf(authUser.getId());

            // 查找卡信息
            Card card = cardMapper.selectById(id);
            if (ObjectUtil.isNull(card)) {
                return ResultUtil.error(ResultCode.ENTITY_NULL);
            }
            Integer faceValue = card.getFaceValue();

            // 获取微信支付设置
            WechatPaymentSetting wechatPaymentSetting = getWechatPaymentSetting(settingService);
            JeepayClient jeepayClient = JeepayClient.getInstance(wechatPaymentSetting.getAppId(), wechatPaymentSetting.getApiKey3());

            // 构建支付请求
            PayOrderCreateRequest request = buildPaymentRequest(card, faceValue, wechatPaymentSetting);

            // 执行支付请求
            PayOrderCreateResponse response = jeepayClient.execute(request);

            // 验签结果
            log.info("验签结果：{}", response.checkSign(Jeepay.apiKey));

            if (response.isSuccess(Jeepay.apiKey)) {
                // 下单成功，保存卡信息
                saveCardInfo(card, userId, response);
                log.info("payOrderId：{}", response.get().getPayOrderId());
                log.info("mchOrderNo：{}", response.get().getMchOrderNo());
                return ResultUtil.success(ResultCode.YAOCHONGXINKANYIXIADAIMA);
            } else {
                log.info("下单失败：{}", request.getBizModel());
                log.info("通道错误码：{}", response.get().getErrCode());
                log.info("通道错误信息：{}", response.get().getErrMsg());
                return ResultUtil.data(response.get().getErrCode());
            }
        } catch (JeepayException e) {
            log.error("支付过程中发生异常: " + e.getMessage(), e);
            return ResultUtil.error(ResultCode.PAYMENT_ERROR);
        }
    }

    /**
     * 这里的提交购买卡订单  可以是次卡、月卡、储值卡、散客储值卡
     *
     * @param accessToken
     * @param orderCardReq
     * @return
     */
    @Override
    public ResultMessage generateCardOrder(String accessToken, OrderCardReq orderCardReq) {
        // 检查参数是否有效
        if (accessToken == null || orderCardReq == null) {
            return ResultUtil.error(ResultCode.USER_NEED_LOGIN);
        }

        // 获取用户ID
        AuthUser authUser = UserContext.getAuthUser(accessToken);
        String userId = authUser.getId();

        // 检查用户是否存在
        User user = userMapper.selectById(userId);
        log.info("此时用户信息为{}", user);
        if (user == null) {
            return ResultUtil.error(ResultCode.USER_NEED_LOGIN);
        }

        //获取卡信息
        Integer cardId = orderCardReq.getCardId();
        CbCardAdmin card = cardAdminMapper.selectById(cardId);
        log.info("此时卡信息为{}", card);

//        //要先校验这个卡是否购买多次
//        String cardType = "MONTHLY";
//        LambdaQueryWrapper<Card> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.eq(Card::getUserId, userId)
//                .eq(Card::getCardType, cardType);
//        List<Card> cards = cardMapper.selectList(lambdaQueryWrapper);
//        if (cards != null) {
//            return ResultUtil.success(ResultCode.CARD_ALREADY_EXITS);
//        }

        //创建订单
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setCreateTime(new Date());
        orderInfo.setUserId(userId);
        orderInfo.setStoreId(orderCardReq.getStoreId());
        orderInfo.setOrderPrice(Double.valueOf(card.getFaceValue()));
        orderInfo.setOrderType(card.getCardType());
        //这里的卡id是指买的哪张卡
        orderInfo.setCardId(cardId);
        orderInfo.setPhoneNumber(user.getPhoneNumber());

        //保存订单 返回id
        boolean save = orderInfoService.save(orderInfo);

        if (save) {
            OrderVo orderVo = new OrderVo();
            String id = orderInfo.getId();
            log.info("这里的订单id为：{}", id);
            orderVo.setCardId(cardId);
            orderVo.setOrderId(id);
            // 订单成功保存后，设置订单的过期时间为15分钟
            String key = "orderInfo:" + orderInfo.getId();
            redisTemplate.opsForValue().set(key, orderInfo, 15, TimeUnit.MINUTES);
            log.info("这里的订单id为：{}", orderInfo.getId());
            return ResultUtil.data(orderVo);
        }
        return ResultUtil.error(ResultCode.ERROR);
    }

    /**
     * 储值卡支付的逻辑还是有点问题 需要改变一下
     * 这里的卡是用户购买之后的卡
     *
     * @param orderId
     * @param cardId
     * @return
     */
    @Override
    public ResultMessage valueCardPay(@NotNull String orderId, @NotNull Integer cardId) {
        //获取当前订单信息
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        log.info("此时的订单信息为:{}", orderInfo);

        //获得使用的储值卡具体信息
        Card card = cardMapper.selectById(cardId);
        log.info("此时的卡信息为:{}", card);
        try {
            //先获取卡的截至时间，看此储值卡是否过期
            String endDate = card.getEndDate();
            endDate = endDate.trim();
            log.info("此时得到卡的截至时间为：{}", endDate);

            // 创建DateTimeFormatter对象，用于解析日期时间字符串
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

            // 将截至日期字符串转换为LocalDate对象
            LocalDate endDateStr = LocalDate.parse(endDate, formatter);

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

            // 比较截至日期和当前日期
            if (currentDate.isAfter(endDateStr)) {
                return ResultUtil.data("储值卡已经过期！");
            } else {
                //获取当前储值卡的余额
                Double currentBalance = card.getCurrentBalance();
                log.info("此时的余额为:{}", currentBalance);
                //这里处理可能为null的情况
                Float discountValue = Optional.ofNullable(card.getDiscountValue())
                        .map(value -> value / 10)
                        .orElse(1.0f);

                Double orderPrice = orderInfo.getOrderPrice();
                log.info("订单价格为:{}", orderPrice);

                double v1 = orderPrice * discountValue;
                log.info("需要支付金额为:{}", v1);

                if (v1 < currentBalance) {
                    double v = currentBalance - v1;
                    log.info("支付之后的余额为:{}", v);
                    card.setCurrentBalance(v);
                    cardMapper.updateById(card);
                    // 支付成功生成二维码
                    // 修改订单状态为已支付
                    orderInfo.setOrderState(String.valueOf(OrderStatusEnum.WAITING_TO_USE));
                    log.info("此时的OrderState信息为{}", orderInfo.getOrderState());

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

                    orderInfoMapper.updateById(orderInfo);

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

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

                    // 格式化日期为字符串
                    DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyyMMdd");
                    String formattedDate = currentDate1.format(formatter1);
                    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();
                        // 转化为时间戳
                        // 前30后30
                        // 获取当前时间的时间戳（秒级）
                        long currentTimeMillis = System.currentTimeMillis() / 1000;

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

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


                        // 如果需要确保不早于当前时间，可以添加以下逻辑
                        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");
                        log.info("此时返回的code为：{}", 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);
                        return ResultUtil.success();
                    }
                }
                return ResultUtil.error(ResultCode.CURRENTBALANCE_NOT);
            }
        } catch (DateTimeParseException e) {
            // 日期字符串解析失败，处理异常情况
            log.error("Failed to parse date string: {}", e);
        }
        return null;
    }

    /**
     * 传入卡id和userid,去得到该用户买这个卡的记录 然后比对卡的类型
     *
     * @param cardId
     * @return
     */
    @Override
    public ResultMessage getQrCodeByCard(@NotNull String cardId) {
        //获取card信息
        Card card = cardMapper.selectById(cardId);
        log.info("此时的card信息为：{}", card);
        //获得此刻的订单信息
        String orderId = card.getOrderId();
        //根据orderId出得到二维码
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        String orderType = orderInfo.getOrderType();
        String cardType = card.getCardType();
        if ("MONTHLY".equals(cardType) && "MONTHLY".equals(orderType)) {
            String qrCode = orderInfo.getQrCode();
            return ResultUtil.data(qrCode);
        }
        return ResultUtil.success(ResultCode.GET_MONTHLY_CODE_ERROR);
    }

    /**
     * 储值卡充值
     *
     * @param orderId
     * @param cardId
     * @return
     */
    @Override
    public ResultMessage cardCharge(String orderId, Integer cardId) {
        return null;
    }

    @Override
    public ResultMessage getChargeCardOrder(String accessToken, Integer cardId, Double currentBalance) {

        // 检查参数是否有效
        if (accessToken == null) {
            return ResultUtil.error(ResultCode.USER_NEED_LOGIN);
        }

        // 获取用户ID
        AuthUser authUser = UserContext.getAuthUser(accessToken);
        String userId = authUser.getId();

        // 检查用户是否存在
        User user = userMapper.selectById(userId);
        if (user == null) {
            return ResultUtil.error(ResultCode.USER_NEED_LOGIN);
        }

        //获取卡信息
        Card card = cardMapper.selectById(cardId);
        log.info("此时的card信息为：{}", card);

        if (ObjectUtil.isNull(card)) {
            return ResultUtil.error(ResultCode.ENTITY_NULL);
        }

        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderType(String.valueOf(orderTypeEnum.STORED_VALUE));
        orderInfo.setCardId(card.getId());
        orderInfo.setStoreId(9376L);
        orderInfo.setCreateTime(new Date());
        orderInfo.setUserId(userId);
        orderInfo.setOverPrice(currentBalance);
        log.info("此时的订单信息为：{}", orderInfo);
        boolean save = orderInfoService.save(orderInfo);
        if (save) {
            // 订单成功保存后，设置订单的过期时间为15分钟
            String key = "orderInfo:" + orderInfo.getId();
            redisTemplate.opsForValue().set(key, orderInfo, 15, TimeUnit.MINUTES);
            log.info("这里的订单id为：{}", orderInfo.getId());
            return ResultUtil.data(orderInfo.getId());
        }
        return ResultUtil.success();
    }

    private PayOrderCreateRequest buildPaymentRequest(Card card, Integer faceValue, WechatPaymentSetting
            paymentSetting) {
        PayOrderCreateRequest request = new PayOrderCreateRequest();
        PayOrderCreateReqModel model = new PayOrderCreateReqModel();
        model.setMchNo(paymentSetting.getMchId());
        model.setAppId(paymentSetting.getAppId());
        String orderNo = "mho" + new Date().getTime();
        model.setMchOrderNo(orderNo);
        model.setWayCode("WX_LITE");
        model.setAmount(Long.valueOf(faceValue));
        model.setCurrency("CNY");
        model.setClientIp("1.14.25.22");
        model.setSubject(card.getCardType());
        model.setBody(card.getCardName());
        request.setBizModel(model);
        return request;
    }

    private void saveCardInfo(Card card, Long userId, PayOrderCreateResponse response) {
        Card cardInfo = new Card();
        cardInfo.setDays(card.getDays());
        cardInfo.setFaceValue(card.getFaceValue());
        cardInfo.setCardType(card.getCardType());
        cardInfo.setBonusAmount(card.getBonusAmount());
        cardInfo.setCurrentBalance((double) (card.getFaceValue() + card.getBonusAmount()));
        cardService.save(cardInfo);
    }
}



