package com.liquidnet.service.goblin.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.dto.vo.GoblinBraceletOrderVo;
import com.liquidnet.service.goblin.dto.vo.GoblinRechargeAmountVo;
import com.liquidnet.service.goblin.dto.vo.GoblinRechargeWristbandVo;
import com.liquidnet.service.goblin.dto.vo.MaiZhiAllVo.*;
import com.liquidnet.service.goblin.entity.GoblinBraceletOrder;
import com.liquidnet.service.goblin.entity.GoblinRechargeAmount;
import com.liquidnet.service.goblin.entity.GoblinRechargeWristband;
import com.liquidnet.service.goblin.mapper.GoblinRechargeAmountMapper;
import com.liquidnet.service.goblin.mapper.GoblinRechargeWristbandMapper;
import com.liquidnet.service.goblin.service.IGoblinBraceletOrderService;
import com.liquidnet.service.goblin.service.IGoblinRechargeWristbandService;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.QueueUtils;
import com.liquidnet.service.goblin.util.ThirdMaiZhiUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * <p>
 * 手环信息表 服务实现类
 * </p>
 *
 * @author jiangxiulong
 * @since 2025-07-03
 */
@Slf4j
@Service
public class GoblinRechargeWristbandServiceImpl extends ServiceImpl<GoblinRechargeWristbandMapper, GoblinRechargeWristband> implements IGoblinRechargeWristbandService {

    @Autowired
    GoblinRedisUtils goblinRedisUtils;

    @Autowired
    private QueueUtils queueUtils;

    @Autowired
    ThirdMaiZhiUtils thirdMaiZhiUtils;

    @Autowired
    private GoblinRechargeAmountMapper rechargeAmountMapper;

    @Autowired
    private GoblinRechargeWristbandMapper rechargeWristbandMapper;

    @Autowired
    private IGoblinBraceletOrderService iGoblinBraceletOrderService;

    @Override
    public GoblinRechargeWristbandVo getList() {
        GoblinRechargeWristbandVo result = goblinRedisUtils.getRechargeWristbandVo();

        if (result == null) {
            // 从数据库中查询数据
            List<GoblinRechargeWristband> rechargeWristbands = rechargeWristbandMapper.selectList(null);
            List<GoblinRechargeAmount> rechargeAmounts = rechargeAmountMapper.selectList(null);

            // 组合数据
            if (!CollectionUtils.isEmpty(rechargeAmounts) && !CollectionUtils.isEmpty(rechargeWristbands)) {
                GoblinRechargeWristbandVo wristbandVo = GoblinRechargeWristbandVo.getNew();
                wristbandVo.setWristbandId(rechargeWristbands.get(0).getWristbandId());
                wristbandVo.setName(rechargeWristbands.get(0).getName());
                wristbandVo.setPrice(rechargeWristbands.get(0).getPrice());
                List<GoblinRechargeAmountVo> list = new ArrayList<>();
                for (GoblinRechargeAmount amount : rechargeAmounts) {
                    GoblinRechargeAmountVo amountVo = GoblinRechargeAmountVo.getNew();
                    amountVo.setAmountId(amount.getAmountId());
                    amountVo.setName(amount.getName());
                    amountVo.setPrice(amount.getPrice());
                    list.add(amountVo);
                }
                wristbandVo.setAmonutList(list);

                goblinRedisUtils.setRechargeWristbandVo(wristbandVo);
                return wristbandVo;
            }
        }

        return result;
    }

    @Override
    public CheckIdcardResponse auth(IdCardParam param) {
        String accessToken = this.getAccessToken();
        if (null != accessToken) {
            return thirdMaiZhiUtils.checkIdcard(accessToken, param.getIdcard(), param.getName());
        }
        return null;
    }

    @Override
    public OrderResponse createOrder(OrderParam param, String orderId) {
        String accessToken = this.getAccessToken();
        if (null != accessToken) {
            OrderResponse addOrder = thirdMaiZhiUtils.addOrder(accessToken, param);
            log.info("createOrder OrderParam:{}", param);
            log.info("createOrder addOrder:{}", addOrder);
            if (addOrder != null && addOrder.getErrcode() == 200) {
                OrderInfoParam orderInfoParam = OrderInfoParam.getNew();
                List<String> orderList = new ArrayList<>();
                orderList.add(param.getDgoid());
                orderInfoParam.setOrderList(orderList);
                OrderInfoResponse order = this.getOrder(orderInfoParam, orderId);
                return addOrder;
            }
        }
        return null;
    }

    @Override
    public OrderInfoResponse getOrder(OrderInfoParam param, String orderId) {
        log.info("getOrder OrderParam:{}", param);
        String accessToken = this.getAccessToken();
        if (null != accessToken) {
            OrderInfoResponse order = thirdMaiZhiUtils.getOrder(accessToken, param);
            log.info("getOrder order:{}", order);
            if (order != null && order.getErrcode() == 200) {
                List<OrderInfoResponse.OrderList> outlist = order.getOutlist();
                OrderInfoResponse.OrderList orderList = outlist.get(0);
                List<OrderInfoResponse.OrderList.UserOrder> userOrder = orderList.getUser_order();
                String foutTradeNo = userOrder.get(0).getFout_trade_no();

                GoblinBraceletOrderVo orderVo = goblinRedisUtils.getBraceletOrderVo(orderId);
                orderVo.setFoutTradeNo(foutTradeNo);
                goblinRedisUtils.setBraceletOrderVo(orderVo);

                LinkedList<String> sqls = CollectionUtil.linkedListString();
                sqls.add(SqlMapping.get("goblin_bracelet_order_update_fout_trade_no"));
                LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();

                sqlDataOrder.add(new Object[]{
                        foutTradeNo, LocalDateTime.now(), orderId
                });

                queueUtils.sendMsgByRedis(
                        MQConst.GoblinQueue.GOBLIN_NFT_ORDER.getKey(),
                        SqlMapping.gets(sqls, sqlDataOrder)
                );

            }
        }
        return null;
    }

    @Override
    public GenerateDeviceCodeResponse getQrcode(String outno) {
        String accessToken = this.getAccessToken();
        if (null != accessToken) {
            return thirdMaiZhiUtils.generateDeviceCode(accessToken, outno);
        }
        return null;
    }

    @Override
    public Boolean getDeviceNumber(Integer operationNo) {
        String accessToken = this.getAccessToken();
        String endtime = goblinRedisUtils.getDeviceNumberEndTime(operationNo);
        if (null != endtime) {
            Instant instant = Instant.EPOCH;
            long timestamp = instant.toEpochMilli();
            endtime = String.valueOf(timestamp);
        }
        long timestamp = Instant.now().toEpochMilli();
        if (null != accessToken) {
            DeviceNumberResponse res = thirdMaiZhiUtils.getDeviceNumber(accessToken, operationNo, endtime, String.valueOf(timestamp));
            if (null != res && res.getErrcode() == 200) {
                for (DeviceNumberResponse.NumberList info : res.getList()) {
                    String orderId = goblinRedisUtils.getOrderIdByFoutTradeNo(info.getFout_trade_no());
                    GoblinBraceletOrderVo orderVo = goblinRedisUtils.getBraceletOrderVo(orderId);
                    if (null != orderVo) {
                        orderVo.setCardno(info.getCardno());
                        goblinRedisUtils.setBraceletOrderVo(orderVo);

                        LinkedList<String> sqls = CollectionUtil.linkedListString();
                        sqls.add(SqlMapping.get("goblin_bracelet_order_update_cardno"));
                        LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();

                        sqlDataOrder.add(new Object[]{
                                info.getCardno(), LocalDateTime.now(), orderId
                        });

                        queueUtils.sendMsgByRedis(
                                MQConst.GoblinQueue.GOBLIN_NFT_ORDER.getKey(),
                                SqlMapping.gets(sqls, sqlDataOrder)
                        );
                    }

                }
                goblinRedisUtils.setDeviceNumberEndTime(operationNo, String.valueOf(timestamp));
                return true;
            }
        }
        return false;
    }

    @Override
    public DeviceBalanceResponse getDeviceBalance(String cardno) {
        String accessToken = this.getAccessToken();
        if (null != accessToken) {
            return thirdMaiZhiUtils.getDeviceBalance(accessToken, cardno);
        }
        return null;
    }

    @Override
    public DeviceRecordResponse getDeviceRecord(String cardno, Integer page) {
        String accessToken = this.getAccessToken();
        if (null != accessToken) {
            return thirdMaiZhiUtils.getDeviceRecord(accessToken, cardno, page);
        }
        return null;
    }

    @Override
    public ChangeDeviceStatusResponse changeDeviceStatus(String orderId, int type) {
        GoblinBraceletOrderVo orderVo = goblinRedisUtils.getBraceletOrderVo(orderId);
        String cardno = orderVo.getCardno();
        String accessToken = this.getAccessToken();
        if (null != accessToken) {
            ChangeDeviceStatusResponse response = thirdMaiZhiUtils.changeDeviceStatus(accessToken, cardno, type);
            if (response.getErrcode() == 200) {
                orderVo.setStatus(3);
                orderVo.setRefundStatus(0);
                goblinRedisUtils.setBraceletOrderVo(orderVo);

                LinkedList<String> sqls = CollectionUtil.linkedListString();
                sqls.add(SqlMapping.get("goblin_bracelet_order_update_refund"));
                LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();
                sqlDataOrder.add(new Object[]{
                        orderVo.getStatus(), orderVo.getRefundStatus(), "", LocalDateTime.now(), orderId
                });
                queueUtils.sendMsgByRedis(
                        MQConst.GoblinQueue.GOBLIN_NFT_ORDER.getKey(),
                        SqlMapping.gets(sqls, sqlDataOrder)
                );
            }
        }
        return null;
    }

    @Override
    public Boolean refundRes() {
        String accessToken = this.getAccessToken();
        if (null != accessToken) {
            List<GoblinBraceletOrder> list = iGoblinBraceletOrderService.list(Wrappers.lambdaQuery(GoblinBraceletOrder.class).eq(GoblinBraceletOrder::getStatus, 3));
            for (GoblinBraceletOrder order : list) {
                String cardno = order.getCardno();
                String orderId = order.getOrderId();
                if (null != cardno && !cardno.isEmpty()) {
                    ChangeDeviceStatusResponse res = thirdMaiZhiUtils.refundRes(accessToken, cardno);
                    if (null != res && res.getErrcode() == 200) {
                        GoblinBraceletOrderVo orderVo = goblinRedisUtils.getBraceletOrderVo(orderId);
                        if (res.getStatus() == 1) {
                            orderVo.setStatus(4);
                            orderVo.setRefundStatus(1);
                            orderVo.setRefundStatusNote("");
                        } else if (res.getStatus() == 2) {
                            orderVo.setStatus(7);
                            orderVo.setRefundStatus(2);
                            orderVo.setRefundStatusNote(res.getNote());
                        }
                        goblinRedisUtils.setBraceletOrderVo(orderVo);

                        LinkedList<String> sqls = CollectionUtil.linkedListString();
                        sqls.add(SqlMapping.get("goblin_bracelet_order_update_refund"));
                        LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();
                        sqlDataOrder.add(new Object[]{
                                orderVo.getStatus(), orderVo.getRefundStatus(), orderVo.getRefundStatusNote(), LocalDateTime.now()
                        });
                        queueUtils.sendMsgByRedis(
                                MQConst.GoblinQueue.GOBLIN_NFT_ORDER.getKey(),
                                SqlMapping.gets(sqls, sqlDataOrder)
                        );
                    }
                }
            }
            return true;
        } else {
            return false;
        }
    }

    private String getAccessToken() {
        String token = goblinRedisUtils.getMaiZhiAccessToken();
        if (null == token) {
            AuthResponse response = thirdMaiZhiUtils.login("CM250001", "95b42275318c6df2d78c43525c2126e7", "380e8acd181abef8c6253721b05a54a1");
            if (response.getErrcode() == 200) {
                token = response.getData().getAccessToken();
                goblinRedisUtils.setMaiZhiAccessToken(token, response.getData().getExpire() - 200);
            }
        }
        return token;
    }

}