package com.yida.data.school.smart.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.common.ResultMsgType;
import com.yida.data.common.core.entity.constant.ConstructionPayConstant;
import com.yida.data.common.core.entity.smart.ConstructionPayNotifyDTO;
import com.yida.data.common.core.entity.smart.EduGuideStepOrder;
import com.yida.data.common.core.entity.system.ConstructionPayConfig;
import com.yida.data.common.core.enums.ConstructionTradeStateEnum;
import com.yida.data.common.core.enums.OrderStatusEnum;
import com.yida.data.common.core.enums.PayStatusEnum;
import com.yida.data.common.core.enums.PayWay;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.core.utils.ConstructionPayUtil;
import com.yida.data.common.core.utils.EnumUtils;
import com.yida.data.common.service.CommonService;
import com.yida.data.school.smart.mapper.EduGuideStepOrderMapper;
import com.yida.data.school.smart.service.EduGuideStepOrderService;
import com.yida.data.school.smart.service.H5EduSmartWelcomeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * 指南步骤订单表 Service实现
 *
 * @author ZYJ
 * @date 2023-06-20 16:48:14
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduGuideStepOrderServiceImpl extends ServiceImpl
        <EduGuideStepOrderMapper, EduGuideStepOrder> implements EduGuideStepOrderService {

    @Lazy
    @Resource
    private H5EduSmartWelcomeService h5EduSmartWelcomeService;

    private final CommonService commonService;

    @Override
    public void constructionPayNotify(ConstructionPayNotifyDTO dto) {
        // 根据订单号查询对应的订单信息
        EduGuideStepOrder order = getOne(new LambdaQueryWrapper<>(new EduGuideStepOrder())
                .eq(EduGuideStepOrder::getOrderCode, dto.getORDERID()));
        if (Objects.isNull(order)) {
            log.error("建行支付回调, 未找到订单信息, orderNO: {}", dto.getORDERID());
            throw new FebsException(ResultMsgType.ORDER_NOT_FOUND.getValue());
        }
        // 返回的订单状态
        String status = dto.getSUCCESS();
        if ("N".equals(status)) {
            log.error("错误状态: {}", order.getOrderCode());
            throw new FebsException(ResultMsgType.SERVER_ERROR.getValue());
        }
        // 判断支付结果是否处理
        if (OrderStatusEnum.PAY_SUCCESS.getStatus().equals(order.getOrderStatus())) {
            log.info("建行支付回调, 该订单已经处理: {}", order.getOrderCode());
            return;
        }
        // 验证金额
        if (order.getPracticalMoney().compareTo(new BigDecimal(dto.getPAYMENT())) != 0) {
            log.error("订单金额错误: {}", order.getOrderCode());
            throw new FebsException(ResultMsgType.ORDER_MONEY_ERROR.getValue());
        }
        // 获取建行配置信息
        ConstructionPayConfig config = commonService.getConstructionPayConfigByDept(order.getDeptId());
        if (Objects.isNull(config)) {
            log.info("建行支付回调, 该学校没有对应的配置信息: {}", order.getDeptId());
            throw new FebsException(ResultMsgType.SERVER_ERROR.getValue());
        }
        // 签名
        String signature = dto.getSIGN();
        // TODO 此处调用查询接口处理数据
        // 验签
//        boolean checkFlag = ConstructionPayUtil.validateSign(dto, signature, config.getPublicKey());
//        if (!checkFlag) {
//            log.error("建行支付回调, 验签失败");
//            throw new FebsException(ResultMsgType.SERVER_ERROR.getValue());
//        }
        if ("Y".equals(status)) {
            h5EduSmartWelcomeService.guideStepOrderPaySuccess(order.getOrderCode(), LocalDateTime.now());
        }
    }

    @Override
    public void updateGuideRosterOrderStatus() {
        // 查询超时订单
        List<EduGuideStepOrder> list = baseMapper.selectTimeOutOrder();
        if (CollUtil.isNotEmpty(list)) {
            for (EduGuideStepOrder order : list) {
                // 建行订单
                if (PayWay.CONSTRUCTION_PAY.getValue().equals(order.getPayWay())) {
                    updateConstructionGuideStepOrderStatus(order);
                }
            }
        }
    }

    private void updateConstructionGuideStepOrderStatus(EduGuideStepOrder order) {
        try {
            // 查询建行支付配置
            ConstructionPayConfig config = commonService.getConstructionPayConfigByDept(order.getDeptId());
            if (Objects.isNull(config)) {
                log.error("当前学校赞未配置建行支付信息");
                return;
            }
            // 主动查询订单支付状态
            JSONObject resultJson = ConstructionPayUtil.queryOrder(config, order.getOrderCode());
            log.info("建行订单查询返回数据, orderCode: {}, resultJson: {}", order.getOrderCode(), resultJson);
            // 返回code
            String code = resultJson.getStr(ConstructionPayConstant.RETURN_CODE_NAME);
            // 无法找到指定的订单 需要直接关闭订单
            if (ConstructionPayConstant.NO_ORDER_CODE.equalsIgnoreCase(code)) {
                order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
                order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
                baseMapper.updateById(order);
                return;
            }

            // 支付信息
            JSONObject queryOrder = resultJson.getJSONObject("QUERYORDER");
            // 支付状态
            String status = (String) queryOrder.get("STATUSCODE");
            // 不确定不处理
            if (ConstructionTradeStateEnum.WAIT_BANK_CONFIRM.getStatus().equals(status)
                    || ConstructionTradeStateEnum.WAIT_BANK_CONFIRM_OTHER.getStatus().equals(status)) {
                return;
            }
            ConstructionTradeStateEnum tradeStateEnum = EnumUtils.valueOf(ConstructionTradeStateEnum.class, status,
                    ConstructionTradeStateEnum.class.getMethod("getStatus"));
            switch (Objects.requireNonNull(tradeStateEnum)) {
                // 支付成功
                case TRADE_SUCCESS:
                    h5EduSmartWelcomeService.guideStepOrderPaySuccess(order.getOrderCode(),
                            LocalDateTimeUtil.parse((String) resultJson.get("ORDERDATE"), DatePattern.NORM_DATETIME_PATTERN));
                    break;
                // 作废订单
                case TRADE_FAIL:
                case WAIT_BANK_CONFIRM:
                case WAIT_BANK_CONFIRM_OTHER:
                    order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
                    order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
                    break;
                default:
                    break;
            }
            if (OrderStatusEnum.CLOSED.getStatus().equals(order.getOrderStatus())) {
                baseMapper.updateById(order);
            }
        } catch (Exception e) {
            log.error("更新建行迎新订单状态失败, order: {}", order, e);
        }
    }
}
