package com.zsElectric.boot.thirdParty.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zsElectric.boot.business.mapper.RechargeLevelMapper;
import com.zsElectric.boot.business.mapper.ThirdPartyEquipmentInfoMapper;
import com.zsElectric.boot.business.mapper.ThirdPartyInfoMapper;
import com.zsElectric.boot.business.mapper.ThirdPartyStationInfoMapper;
import com.zsElectric.boot.business.model.vo.applet.AppletConnectorDetailVO;
import com.zsElectric.boot.charging.mapper.ThirdPartyConnectorInfoMapper;
import com.zsElectric.boot.business.mapper.UserAccountMapper;
import com.zsElectric.boot.business.mapper.UserOrderInfoMapper;
import com.zsElectric.boot.business.model.entity.RechargeLevel;
import com.zsElectric.boot.business.model.entity.ThirdPartyInfo;
import com.zsElectric.boot.business.model.entity.UserAccount;
import com.zsElectric.boot.business.model.entity.UserInfo;
import com.zsElectric.boot.business.model.entity.UserOrderInfo;
import com.zsElectric.boot.business.model.query.StationInfoQuery;
import com.zsElectric.boot.business.model.vo.AppletStationDetailVO;
import com.zsElectric.boot.business.model.vo.StationInfoVO;
import com.zsElectric.boot.charging.entity.ThirdPartyConnectorInfo;
import com.zsElectric.boot.charging.entity.ThirdPartyEquipmentInfo;
import com.zsElectric.boot.charging.entity.ThirdPartyStationInfo;
import com.zsElectric.boot.business.service.UserInfoService;
import com.zsElectric.boot.business.service.UserAccountService;
import com.zsElectric.boot.common.constant.SystemConstants;
import com.zsElectric.boot.common.util.AESCryptoUtils;
import com.zsElectric.boot.common.util.HmacMD5Util;
import com.zsElectric.boot.thirdParty.model.*;
import com.zsElectric.boot.thirdParty.service.ThirdPartyTokenService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 第三方Token服务实现类
 *
 * @author wzq
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ThirdPartyTokenServiceImpl implements ThirdPartyTokenService {

    private final ThirdPartyInfoMapper thirdPartyInfoMapper;
    private final RechargeLevelMapper rechargeLevelMapper;
    private final RedisTemplate<String, Object> redisTemplate;
    private final UserInfoService userInfoService;
    private final UserAccountMapper userAccountMapper;
    private final UserAccountService userAccountService;
    private final UserOrderInfoMapper userOrderInfoMapper;
    private final ThirdPartyStationInfoMapper thirdPartyStationInfoMapper;
    private final ThirdPartyEquipmentInfoMapper thirdPartyEquipmentInfoMapper;
    private final ThirdPartyConnectorInfoMapper thirdPartyConnectorInfoMapper;
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * Redis Token Key 前缀
     */
    private static final String TOKEN_KEY_PREFIX = "third_party_access:token:";

    /**
     * Redis OperatorId Token映射 Key 前缀
     */
    private static final String OPERATOR_TOKEN_KEY_PREFIX = "third_party_access:operator:";

    /**
     * 默认Token有效期（秒）
     */
    private static final int DEFAULT_TOKEN_EXPIRE_SECONDS = 7200;

    @Override
    public ThirdPartyResponse queryToken(ThirdPartyRequest request) {
        try {
            // 1. 参数校验
            if (!validateRequestParams(request)) {
                return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
            }

            // 2. 通过operatorId查询第三方配置信息
            ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
            if (thirdPartyInfo == null) {
                log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4004, "运营商不存在", null);
            }

            // 3. 验证签名
            String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
            if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
                log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
            }

            // 4. 解密并解析业务参数
            String decryptedData = AESCryptoUtils.decrypt(
                    request.getData(),
                    thirdPartyInfo.getDataSecret(),
                    thirdPartyInfo.getDataSecretIV()
            );
            log.info("解密后的请求数据: {}", decryptedData);

            QueryTokenRequestData tokenRequest = objectMapper.readValue(decryptedData, QueryTokenRequestData.class);
            if (tokenRequest == null || StrUtil.isBlank(tokenRequest.getOperatorId()) || StrUtil.isBlank(tokenRequest.getOperatorSecret())) {
                return buildErrorResponse(4004, "请求的业务参数不合法", thirdPartyInfo);
            }

            // 5. 验证运营商ID和密钥
            if (!thirdPartyInfo.getOperatorId().equals(tokenRequest.getOperatorId())
                    || !thirdPartyInfo.getOperatorSecret().equals(tokenRequest.getOperatorSecret())) {
                log.warn("运营商ID或密钥错误, operatorId: {}", tokenRequest.getOperatorId());
                // 返回失败响应数据
                QueryTokenResponseData failData = QueryTokenResponseData.fail(tokenRequest.getOperatorId(), 1);
                return buildSuccessResponse(failData, thirdPartyInfo);
            }

            // 6. 生成或获取已有Token
            String accessToken = getOrGenerateToken(tokenRequest.getOperatorId());
            Integer remainingTTL = getRemainingTTL(accessToken);

            // 7. 构建成功响应
            QueryTokenResponseData responseData = QueryTokenResponseData.success(
                    tokenRequest.getOperatorId(),
                    accessToken,
                    remainingTTL
            );
            log.info("生成Token成功, operatorId: {}, token有效期: {}秒", tokenRequest.getOperatorId(), remainingTTL);

            return buildSuccessResponse(responseData, thirdPartyInfo);

        } catch (Exception e) {
            log.error("处理query_token请求异常", e);
            return buildErrorResponse(500, "系统错误", null);
        }
    }

    @Override
    public ThirdPartyResponse queryRechargeLevelPage(ThirdPartyRequest request, String authorization) {
        try {
            // 1. 参数校验
            if (!validateRequestParams(request)) {
                return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
            }

            // 2. 通过operatorId查询第三方配置信息
            ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
            if (thirdPartyInfo == null) {
                log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4004, "运营商不存在", null);
            }

            // 3. 验证签名
            String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
            if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
                log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
            }

            // 4. 从Header中解析并验证Token
            String accessToken = parseAccessToken(authorization);
            if (StrUtil.isBlank(accessToken)) {
                log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }
            if (!validateAccessToken(accessToken, request.getOperatorId())) {
                log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }

            // 5. 解密并解析业务参数
            String decryptedData = AESCryptoUtils.decrypt(
                    request.getData(),
                    thirdPartyInfo.getDataSecret(),
                    thirdPartyInfo.getDataSecretIV()
            );
            log.info("解密后的请求数据: {}", decryptedData);

            RechargeLevelPageRequestData pageRequest = objectMapper.readValue(decryptedData, RechargeLevelPageRequestData.class);
            if (pageRequest == null) {
                pageRequest = new RechargeLevelPageRequestData();
            }

            // 6. 查询充值档位分页数据
            IPage<RechargeLevel> pageResult = queryRechargeLevelFromDb(pageRequest);

            // 7. 转换为响应数据
            List<RechargeLevelPageResponseData.RechargeLevelItem> records = pageResult.getRecords().stream()
                    .map(this::convertToItem)
                    .collect(Collectors.toList());

            RechargeLevelPageResponseData responseData = RechargeLevelPageResponseData.of(
                    pageResult.getTotal(),
                    (int) pageResult.getCurrent(),
                    (int) pageResult.getSize(),
                    pageResult.getPages(),
                    records
            );

            log.info("查询充值档位成功, operatorId: {}, total: {}", request.getOperatorId(), pageResult.getTotal());
            return buildSuccessResponse(responseData, thirdPartyInfo);

        } catch (Exception e) {
            log.error("处理query_recharge_level_page请求异常", e);
            return buildErrorResponse(500, "系统错误", null);
        }
    }

    @Override
    public ThirdPartyResponse queryUserInfo(ThirdPartyRequest request, String authorization) {
        try {
            // 1. 参数校验
            if (!validateRequestParams(request)) {
                return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
            }

            // 2. 通过operatorId查询第三方配置信息
            ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
            if (thirdPartyInfo == null) {
                log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4004, "运营商不存在", null);
            }

            // 3. 验证签名
            String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
            if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
                log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
            }

            // 4. 从Header中解析并验证Token
            String accessToken = parseAccessToken(authorization);
            if (StrUtil.isBlank(accessToken)) {
                log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }
            if (!validateAccessToken(accessToken, request.getOperatorId())) {
                log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }

            // 5. 解密并解析业务参数
            String decryptedData = AESCryptoUtils.decrypt(
                    request.getData(),
                    thirdPartyInfo.getDataSecret(),
                    thirdPartyInfo.getDataSecretIV()
            );
            log.info("解密后的请求数据: {}", decryptedData);

            QueryUserInfoRequestData userInfoRequest = objectMapper.readValue(decryptedData, QueryUserInfoRequestData.class);
            if (userInfoRequest == null || StrUtil.isBlank(userInfoRequest.getPhone())) {
                log.warn("手机号为空, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4004, "请求的业务参数不合法,手机号不能为空", thirdPartyInfo);
            }

            String phone = userInfoRequest.getPhone();

            // 6. 根据手机号查询用户信息
            UserInfo userInfo = userInfoService.getUserInfoByPhone(phone);

            Integer isNewUser = 0;
            if (userInfo == null) {
                // 用户不存在，注册新用户
                log.info("用户不存在，注册新用户, phone: {}", phone);
                userInfo = userInfoService.registerOrUpdateUserByPhone(phone, null);
                if (userInfo == null) {
                    log.error("注册用户失败, phone: {}", phone);
                    return buildErrorResponse(500, "注册用户失败", thirdPartyInfo);
                }
                isNewUser = 1;
            }

            // 7. 查询用户账户信息
            UserAccount userAccount = userAccountMapper.selectOne(
                    Wrappers.<UserAccount>lambdaQuery()
                            .eq(UserAccount::getUserId, userInfo.getId())
                            .eq(UserAccount::getIsDeleted, 0)
            );

            // 如果账户不存在，创建账户
            if (userAccount == null) {
                log.info("用户账户不存在，创建账户, userId: {}", userInfo.getId());
                userAccount = new UserAccount();
                userAccount.setUserId(userInfo.getId());
                userAccount.setBalance(BigDecimal.ZERO);
                userAccount.setRedeemBalance(BigDecimal.ZERO);
                userAccount.setIntegral(BigDecimal.ZERO);
                userAccountMapper.insert(userAccount);
            }

            // 8. 构建响应数据
            QueryUserInfoResponseData.UserInfoItem userInfoItem = new QueryUserInfoResponseData.UserInfoItem();
            userInfoItem.setUserId(userInfo.getId());
            userInfoItem.setNickName(userInfo.getNickName());
            userInfoItem.setPhone(userInfo.getPhone());
            userInfoItem.setOpenid(userInfo.getOpenid());

            QueryUserInfoResponseData.AccountInfoItem accountInfoItem = new QueryUserInfoResponseData.AccountInfoItem();
            accountInfoItem.setAccountId(userAccount.getId());
            accountInfoItem.setBalance(userAccount.getBalance() != null ? userAccount.getBalance() : BigDecimal.ZERO);
            accountInfoItem.setRedeemBalance(userAccount.getRedeemBalance() != null ? userAccount.getRedeemBalance() : BigDecimal.ZERO);
            accountInfoItem.setIntegral(userAccount.getIntegral() != null ? userAccount.getIntegral() : BigDecimal.ZERO);

            QueryUserInfoResponseData responseData = QueryUserInfoResponseData.of(isNewUser, userInfoItem, accountInfoItem);

            log.info("根据手机号查询用户信息成功, operatorId: {}, phone: {}, isNewUser: {}", request.getOperatorId(), phone, isNewUser);
            return buildSuccessResponse(responseData, thirdPartyInfo);

        } catch (Exception e) {
            log.error("处理query_user_info请求异常", e);
            return buildErrorResponse(500, "系统错误", null);
        }
    }

    @Override
    public ThirdPartyResponse chargeOrderPay(ThirdPartyRequest request, String authorization) {
        try {
            // 1. 参数校验
            if (!validateRequestParams(request)) {
                return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
            }

            // 2. 通过operatorId查询第三方配置信息
            ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
            if (thirdPartyInfo == null) {
                log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4004, "运营商不存在", null);
            }

            // 3. 验证签名
            String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
            if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
                log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
            }

            // 4. 从Header中解析并验证Token
            String accessToken = parseAccessToken(authorization);
            if (StrUtil.isBlank(accessToken)) {
                log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }
            if (!validateAccessToken(accessToken, request.getOperatorId())) {
                log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }

            // 5. 解密并解析业务参数
            String decryptedData = AESCryptoUtils.decrypt(
                    request.getData(),
                    thirdPartyInfo.getDataSecret(),
                    thirdPartyInfo.getDataSecretIV()
            );
            log.info("解密后的请求数据: {}", decryptedData);

            ChangeOrderPayRequestData payRequest = objectMapper.readValue(decryptedData, ChangeOrderPayRequestData.class);
            if (payRequest == null || StrUtil.isBlank(payRequest.getPhone()) || StrUtil.isBlank(payRequest.getOrderNo())) {
                log.warn("请求参数不完整, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4004, "请求的业务参数不合法,手机号和订单号不能为空", thirdPartyInfo);
            }

            Long userId = payRequest.getUserId();
            String phone = payRequest.getPhone();
            //根据userId和phone校验用户
            UserInfo userInfo = userInfoService.getOne(Wrappers.lambdaQuery(UserInfo.class).eq(UserInfo::getPhone, phone).eq(UserInfo::getId, userId).last("limit 1"));
            if (ObjectUtil.isNull(userInfo)) {
                log.warn("用户不存在, userId: {}, phone: {}", userId, phone);
                ChargeOrderPayResponseData failData = ChargeOrderPayResponseData.fail("用户不存在");
                return buildSuccessResponse(failData, thirdPartyInfo);
            }
            String orderNo = payRequest.getOrderNo();
            UserAccount userAccount = userAccountService.getOne(Wrappers.lambdaQuery(UserAccount.class).eq(UserAccount::getUserId, userId).last("limit 1"));
            // 如果账户不存在，创建账户
            if (ObjectUtil.isNull(userAccount)) {
                log.info("用户账户不存在，创建账户, userId: {}", userInfo.getId());
                userAccount = new UserAccount();
                userAccount.setUserId(userInfo.getId());
                userAccount.setBalance(BigDecimal.ZERO);
                userAccount.setRedeemBalance(BigDecimal.ZERO);
                userAccount.setIntegral(BigDecimal.ZERO);
                userAccountMapper.insert(userAccount);
            }

            // 6. 幂等性检查 - 通过Redis检查订单是否已处理
            String orderKey = "third_party_pay:order:" + orderNo;
            Boolean isProcessed = redisTemplate.hasKey(orderKey);
            if (Boolean.TRUE.equals(isProcessed)) {
                log.warn("订单已处理，请勿重复提交, orderNo: {}", orderNo);
                ChargeOrderPayResponseData failData = ChargeOrderPayResponseData.fail("订单已处理，请勿重复提交");
                return buildSuccessResponse(failData, thirdPartyInfo);
            }

            // 7. 查询充值档位信息（如果有levelId）
            BigDecimal rechargeMoney;
            if (payRequest.getLevelId() != null) {
                RechargeLevel rechargeLevel = rechargeLevelMapper.selectById(payRequest.getLevelId());
                if (rechargeLevel == null) {
                    log.warn("充值档位不存在, levelId: {}", payRequest.getLevelId());
                    ChargeOrderPayResponseData failData = ChargeOrderPayResponseData.fail("充值档位不存在");
                    return buildSuccessResponse(failData, thirdPartyInfo);
                }
                rechargeMoney = rechargeLevel.getMoney();
            } else if (StrUtil.isNotBlank(payRequest.getTotalMoney())) {
                // 使用传入的金额
                rechargeMoney = new BigDecimal(payRequest.getTotalMoney());
            } else {
                log.warn("充值金额未指定, operatorId: {}", request.getOperatorId());
                ChargeOrderPayResponseData failData = ChargeOrderPayResponseData.fail("充值金额未指定");
                return buildSuccessResponse(failData, thirdPartyInfo);
            }

            // 8. 增加充值订单记录到c_user_order_info表
            UserOrderInfo orderInfo = new UserOrderInfo();
            orderInfo.setUserId(userId);
            orderInfo.setOrderNo(orderNo);
            orderInfo.setOrderMoney(rechargeMoney);
            orderInfo.setPayMoney(rechargeMoney);
            orderInfo.setLastMoney(rechargeMoney);
            // 解析支付时间
            if (StrUtil.isNotBlank(payRequest.getPayTime())) {
                try {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    orderInfo.setPayTime(LocalDateTime.parse(payRequest.getPayTime(), formatter));
                } catch (Exception e) {
                    orderInfo.setPayTime(LocalDateTime.now());
                }
            } else {
                orderInfo.setPayTime(LocalDateTime.now());
            }
            orderInfo.setLevelId(payRequest.getLevelId());
            orderInfo.setOutTradeNo(orderNo);  // 第三方订单号
            orderInfo.setOrderStatus(2);  // 已支付
            orderInfo.setOrderType(3);    // 渠道方
            orderInfo.setRemark("第三方渠道充值-" + request.getOperatorId());
            userOrderInfoMapper.insert(orderInfo);
            log.info("创建充值订单记录成功, orderNo: {}, userId: {}", orderNo, userId);

            // 9. 充值账户余额并记录日志
            // 使用订单号的Id值作为变更记录ID
            Long changeId = orderInfo.getId();
            UserAccount updatedAccount = userAccountService.updateAccountBalanceAndLog(
                    userId,
                    rechargeMoney,
                    SystemConstants.CHANGE_TYPE_ADD,
                    SystemConstants.ACCOUNT_LOG_THIRD_PARTY_PAY_NOTE + "-" + orderNo,
                    changeId
            );

            BigDecimal balanceAfter = updatedAccount != null ? updatedAccount.getBalance() : userAccount.getBalance().add(rechargeMoney);

            // 10. 构建成功响应
            ChargeOrderPayResponseData responseData = ChargeOrderPayResponseData.success(
                    userId,
                    rechargeMoney,
                    balanceAfter,
                    orderNo
            );

            log.info("充电券购买成功, operatorId: {}, phone: {}, orderNo: {}, rechargeMoney: {}, balanceAfter: {}",
                    request.getOperatorId(), phone, orderNo, rechargeMoney, balanceAfter);
            return buildSuccessResponse(responseData, thirdPartyInfo);

        } catch (Exception e) {
            log.error("处理charge_order_pay请求异常", e);
            return buildErrorResponse(500, "系统错误", null);
        }
    }

    /**
     * 从Authorization Header中解析Token
     * 支持格式: "Bearer {token}" 或直接传 "{token}"
     */
    private String parseAccessToken(String authorization) {
        if (StrUtil.isBlank(authorization)) {
            return null;
        }
        // 支持 Bearer Token 格式
        if (authorization.startsWith("Bearer ")) {
            return authorization.substring(7).trim();
        }
        // 直接返回Token
        return authorization.trim();
    }

    /**
     * 验证访问Token
     */
    private boolean validateAccessToken(String accessToken, String operatorId) {
        String tokenKey = TOKEN_KEY_PREFIX + accessToken;
        String storedOperatorId = (String) redisTemplate.opsForValue().get(tokenKey);
        return operatorId.equals(storedOperatorId);
    }

    /**
     * 从数据库查询充值档位分页数据
     */
    private IPage<RechargeLevel> queryRechargeLevelFromDb(RechargeLevelPageRequestData pageRequest) {
        Page<RechargeLevel> page = new Page<>(pageRequest.getPageNum(), pageRequest.getPageSize());
        LambdaQueryWrapper<RechargeLevel> queryWrapper = new LambdaQueryWrapper<>();

        // 按ID排序
        queryWrapper.eq(RechargeLevel::getStatus, SystemConstants.STATUS_ONE);
        queryWrapper.orderByAsc(RechargeLevel::getId);

        return rechargeLevelMapper.selectPage(page, queryWrapper);
    }

    /**
     * 转换为响应项
     */
    private RechargeLevelPageResponseData.RechargeLevelItem convertToItem(RechargeLevel entity) {
        RechargeLevelPageResponseData.RechargeLevelItem item = new RechargeLevelPageResponseData.RechargeLevelItem();
        item.setId(entity.getId());
        item.setName(entity.getName());
        item.setMoney(entity.getMoney());
        item.setStatus(entity.getStatus());
        item.setTips(entity.getTips());
        return item;
    }

    /**
     * 通过operatorId查询第三方配置信息
     */
    private ThirdPartyInfo getThirdPartyInfoByOperatorId(String operatorId) {
        LambdaQueryWrapper<ThirdPartyInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ThirdPartyInfo::getOperatorId, operatorId)
                .eq(ThirdPartyInfo::getStatus, 0)  // 状态正常
                .last("LIMIT 1");
        return thirdPartyInfoMapper.selectOne(queryWrapper);
    }

    /**
     * 校验请求参数完整性
     */
    private boolean validateRequestParams(ThirdPartyRequest request) {
        return request != null
                && StrUtil.isNotBlank(request.getOperatorId())
                && StrUtil.isNotBlank(request.getData())
                && StrUtil.isNotBlank(request.getTimeStamp())
                && StrUtil.isNotBlank(request.getSeq())
                && StrUtil.isNotBlank(request.getSig());
    }

    /**
     * 获取或生成Token
     * 如果Redis中存在有效Token则返回，否则生成新Token
     */
    private String getOrGenerateToken(String operatorId) {
        // 检查是否有已存在的有效Token
        String operatorTokenKey = OPERATOR_TOKEN_KEY_PREFIX + operatorId;
        String existingToken = (String) redisTemplate.opsForValue().get(operatorTokenKey);

        if (StrUtil.isNotBlank(existingToken)) {
            // 验证Token是否仍然有效
            String tokenKey = TOKEN_KEY_PREFIX + existingToken;
            Boolean hasKey = redisTemplate.hasKey(tokenKey);
            if (Boolean.TRUE.equals(hasKey)) {
                log.info("返回已存在的有效Token, operatorId: {}", operatorId);
                return existingToken;
            }
        }

        // 生成新Token
        String newToken = IdUtil.fastSimpleUUID() + IdUtil.fastSimpleUUID();

        // 存储Token
        String tokenKey = TOKEN_KEY_PREFIX + newToken;
        redisTemplate.opsForValue().set(tokenKey, operatorId, DEFAULT_TOKEN_EXPIRE_SECONDS, TimeUnit.SECONDS);

        // 存储OperatorId与Token的映射关系
        redisTemplate.opsForValue().set(operatorTokenKey, newToken, DEFAULT_TOKEN_EXPIRE_SECONDS, TimeUnit.SECONDS);

        log.info("生成新Token, operatorId: {}, expireSeconds: {}", operatorId, DEFAULT_TOKEN_EXPIRE_SECONDS);
        return newToken;
    }

    /**
     * 获取Token剩余有效时间(秒)
     */
    private Integer getRemainingTTL(String token) {
        String tokenKey = TOKEN_KEY_PREFIX + token;
        Long ttl = redisTemplate.getExpire(tokenKey, TimeUnit.SECONDS);
        return ttl != null && ttl > 0 ? ttl.intValue() : 0;
    }

    /**
     * 构建成功响应（通用）
     */
    private ThirdPartyResponse buildSuccessResponse(Object responseData, ThirdPartyInfo thirdPartyInfo) throws Exception {
        String jsonData = objectMapper.writeValueAsString(responseData);
        String encryptedData = AESCryptoUtils.encrypt(
                jsonData,
                thirdPartyInfo.getDataSecret(),
                thirdPartyInfo.getDataSecretIV()
        );
        String sig = HmacMD5Util.genSign(0, "", encryptedData, thirdPartyInfo.getSigSecret());
        return ThirdPartyResponse.success(encryptedData, sig);
    }

    /**
     * 构建错误响应
     */
    private ThirdPartyResponse buildErrorResponse(Integer ret, String msg, ThirdPartyInfo thirdPartyInfo) {
        try {
            String sigSecret = thirdPartyInfo != null ? thirdPartyInfo.getSigSecret() : "";
            String sig = StrUtil.isNotBlank(sigSecret) ? HmacMD5Util.genSign(ret, msg, "", sigSecret) : "";
            return ThirdPartyResponse.error(ret, msg, sig);
        } catch (Exception e) {
            log.error("生成错误响应签名失败", e);
            ThirdPartyResponse response = new ThirdPartyResponse();
            response.setRet(ret);
            response.setMsg(msg);
            response.setData("");
            response.setSig("");
            return response;
        }
    }

    // ==================== 充电站与设备查询接口 ====================
    /**
     * 时间格式化器 HHmmss
     */
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HHmmss");

    @Override
    public ThirdPartyResponse queryChargeStationList(ThirdPartyRequest request, String authorization) {
        try {
            // 1. 参数校验
            if (!validateRequestParams(request)) {
                return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
            }

            // 2. 通过operatorId查询第三方配置信息
            ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
            if (thirdPartyInfo == null) {
                log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4004, "运营商不存在", null);
            }

            // 3. 验证签名
            String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
            if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
                log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
            }

            // 4. 从Header中解析并验证Token
            String accessToken = parseAccessToken(authorization);
            if (StrUtil.isBlank(accessToken)) {
                log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }
            if (!validateAccessToken(accessToken, request.getOperatorId())) {
                log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }

            // 5. 解密并解析业务参数
            String decryptedData = AESCryptoUtils.decrypt(
                    request.getData(),
                    thirdPartyInfo.getDataSecret(),
                    thirdPartyInfo.getDataSecretIV()
            );
            log.info("解密后的请求数据: {}", decryptedData);

            ChargeStationListRequestData listRequest = objectMapper.readValue(decryptedData, ChargeStationListRequestData.class);
            if (listRequest == null) {
                listRequest = new ChargeStationListRequestData();
            }

            // 6. 查询充电站分页数据
            // 获取当前时间(HHmmss格式)
            String currentTime = LocalTime.now().format(TIME_FORMATTER);

            // 构建分页对象
            Page<StationInfoVO> page = new Page<>(listRequest.getPageNum(), listRequest.getPageSize());

            StationInfoQuery stationInfoQuery = new StationInfoQuery().setLatitude(listRequest.getLatitude()).setLongitude(listRequest.getLongitude()).setSortType(listRequest.getSortType());
            // 执行查询
            IPage<StationInfoVO> pageResult = thirdPartyStationInfoMapper.selectAppletStationInfoPage(
                    page, stationInfoQuery, currentTime, null
            );

            // 7. 转换为响应数据
            List<ChargeStationListResponseData.StationItem> records = pageResult.getRecords().stream()
                    .map(this::convertToStationItem)
                    .collect(Collectors.toList());

            ChargeStationListResponseData responseData = ChargeStationListResponseData.of(
                    pageResult.getTotal(),
                    (int) pageResult.getCurrent(),
                    (int) pageResult.getSize(),
                    pageResult.getPages(),
                    records
            );

            log.info("查询充电站列表成功, operatorId: {}, total: {}", request.getOperatorId(), pageResult.getTotal());
            return buildSuccessResponse(responseData, thirdPartyInfo);

        } catch (Exception e) {
            log.error("处理query_charge_station_list请求异常", e);
            return buildErrorResponse(500, "系统错误", null);
        }
    }

    @Override
    public ThirdPartyResponse queryChargeStationDetail(ThirdPartyRequest request, String authorization) {
        try {
            // 1. 参数校验
            if (!validateRequestParams(request)) {
                return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
            }

            // 2. 通过operatorId查询第三方配置信息
            ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
            if (thirdPartyInfo == null) {
                log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4004, "运营商不存在", null);
            }

            // 3. 验证签名
            String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
            if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
                log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
            }

            // 4. 从Header中解析并验证Token
            String accessToken = parseAccessToken(authorization);
            if (StrUtil.isBlank(accessToken)) {
                log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }
            if (!validateAccessToken(accessToken, request.getOperatorId())) {
                log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }

            // 5. 解密并解析业务参数
            String decryptedData = AESCryptoUtils.decrypt(
                    request.getData(),
                    thirdPartyInfo.getDataSecret(),
                    thirdPartyInfo.getDataSecretIV()
            );
            log.info("解密后的请求数据: {}", decryptedData);

            ChargeStationDetailRequestData detailRequest = objectMapper.readValue(decryptedData, ChargeStationDetailRequestData.class);
            if (detailRequest == null || (detailRequest.getStationId() == null )) {
                return buildErrorResponse(4003, "请求的业务参数不合法", thirdPartyInfo);
            }

            // 6. 查询充电站详情
            // 获取当前时间(HHmmss格式)
            String currentTime = LocalTime.now().format(TIME_FORMATTER);

            // 查询站点详情基本信息
            AppletStationDetailVO result = thirdPartyStationInfoMapper.selectStationDetail(
                    detailRequest.getStationId(), detailRequest.getLongitude(), detailRequest.getLatitude(), currentTime, null
            );

            if (result == null) {
                return buildErrorResponse(4004, "充电站不存在", thirdPartyInfo);
            }

            // 查询站点对应的stationId
            ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectById(detailRequest.getStationId());
            if (stationInfo == null) {
                return buildErrorResponse(4004, "充电站不存在", thirdPartyInfo);
            }

            // 根据站点stationId查询设备列表（third_party_equipment_info）
            List<ThirdPartyEquipmentInfo> equipmentList = thirdPartyEquipmentInfoMapper.selectList(
                    new LambdaQueryWrapper<ThirdPartyEquipmentInfo>()
                            .eq(ThirdPartyEquipmentInfo::getStationId, stationInfo.getStationId())
            );

            // 构建设备ID到设备类型的映射
            Map<String, Integer> equipmentTypeMap = equipmentList.stream()
                    .collect(Collectors.toMap(
                            ThirdPartyEquipmentInfo::getEquipmentId,
                            e -> e.getEquipmentType() != null ? e.getEquipmentType() : 0,
                            (v1, v2) -> v1
                    ));

            // 根据设备列表的equipmentId查询充电接口信息（third_party_connector_info）
            List<ThirdPartyConnectorInfo> connectorList = new ArrayList<>();
            if (!equipmentList.isEmpty()) {
                List<String> equipmentIds = equipmentList.stream()
                        .map(ThirdPartyEquipmentInfo::getEquipmentId)
                        .collect(Collectors.toList());
                connectorList = thirdPartyConnectorInfoMapper.selectList(
                        new LambdaQueryWrapper<ThirdPartyConnectorInfo>()
                                .in(ThirdPartyConnectorInfo::getEquipmentId, equipmentIds)
                );
            }

            // 统计终端状态
            int idleCount = 0;
            int occupiedCount = 0;
            int offlineCount = 0;

            List<AppletStationDetailVO.ConnectorInfoVO> connectorVOList = new ArrayList<>();
            for (ThirdPartyConnectorInfo connector : connectorList) {
                AppletStationDetailVO.ConnectorInfoVO vo = new AppletStationDetailVO.ConnectorInfoVO();
                vo.setConnectorId(connector.getId());
                vo.setConnectorName(connector.getConnectorName());
                vo.setConnectorCode(connector.getConnectorId());

                // 设备分类：从设备表获取设备类型（1-直流设备,2-交流设备,3-交直流一体设备,4-无线设备,5-其他）
                Integer equipmentType = equipmentTypeMap.get(connector.getEquipmentId());
                if (equipmentType != null) {
                    switch (equipmentType) {
                        case 1:
                            vo.setEquipmentType("直流设备");
                            break;
                        case 2:
                            vo.setEquipmentType("交流设备");
                            break;
                        case 3:
                            vo.setEquipmentType("交直流一体设备");
                            break;
                        case 4:
                            vo.setEquipmentType("无线设备");
                            break;
                        case 5:
                            vo.setEquipmentType("其他");
                            break;
                        default:
                            vo.setEquipmentType("未知");
                    }
                }

                // 从充电接口表获取实际状态
                // 0-离网,1-空闲,2-占用(未充电),3-占用(充电中),4-占用(预约锁定),255-故障
                Integer connectorStatus = connector.getStatus();
                if (connectorStatus == null) {
                    // 默认为离网
                    connectorStatus = 0;
                }
                vo.setStatus(connectorStatus);

                // 设置状态名称并统计
                switch (connectorStatus) {
                    case 0:
                        vo.setStatusName("离网");
                        offlineCount++;
                        break;
                    case 1:
                        vo.setStatusName("空闲");
                        idleCount++;
                        break;
                    case 2:
                        vo.setStatusName("占用(未充电)");
                        occupiedCount++;
                        break;
                    case 3:
                        vo.setStatusName("占用(充电中)");
                        occupiedCount++;
                        break;
                    case 4:
                        vo.setStatusName("占用(预约锁定)");
                        occupiedCount++;
                        break;
                    case 255:
                        vo.setStatusName("故障");
                        offlineCount++;
                        break;
                    default:
                        vo.setStatusName("未知");
                        offlineCount++;
                }

                connectorVOList.add(vo);
            }

            result.setConnectorList(connectorVOList);
            result.setIdleCount(idleCount);
            result.setOccupiedCount(occupiedCount);
            result.setOfflineCount(offlineCount);

            // 7. 转换为响应数据
            ChargeStationDetailResponseData responseData = convertToStationDetail(result);

            log.info("查询充电站详情成功, operatorId: {}, stationId: {}", request.getOperatorId(), stationInfo.getStationId());
            return buildSuccessResponse(responseData, thirdPartyInfo);

        } catch (Exception e) {
            log.error("处理query_charge_station_detail请求异常", e);
            return buildErrorResponse(500, "系统错误", null);
        }
    }

    @Override
    public ThirdPartyResponse queryChargeDeviceDetail(ThirdPartyRequest request, String authorization) {
        try {
            // 1. 参数校验
            if (!validateRequestParams(request)) {
                return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
            }

            // 2. 通过operatorId查询第三方配置信息
            ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
            if (thirdPartyInfo == null) {
                log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4004, "运营商不存在", null);
            }

            // 3. 验证签名
            String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
            if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
                log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
            }

            // 4. 从Header中解析并验证Token
            String accessToken = parseAccessToken(authorization);
            if (StrUtil.isBlank(accessToken)) {
                log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }
            if (!validateAccessToken(accessToken, request.getOperatorId())) {
                log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
                return buildErrorResponse(4002, "token错误", thirdPartyInfo);
            }

            // 5. 解密并解析业务参数
            String decryptedData = AESCryptoUtils.decrypt(
                    request.getData(),
                    thirdPartyInfo.getDataSecret(),
                    thirdPartyInfo.getDataSecretIV()
            );
            log.info("解密后的请求数据: {}", decryptedData);

            ChargeDeviceDetailRequestData detailRequest = objectMapper.readValue(decryptedData, ChargeDeviceDetailRequestData.class);
            if (detailRequest == null || (detailRequest.getId() == null && StrUtil.isBlank(detailRequest.getEquipmentId()))) {
                return buildErrorResponse(4003, "请求的业务参数不合法", thirdPartyInfo);
            }

            // 6. 查询充电设备详情
            // 获取当前时间(HHmmss格式)
            String currentTime = LocalTime.now().format(TIME_FORMATTER);

            AppletConnectorDetailVO result = thirdPartyConnectorInfoMapper.selectConnectorDetailById(
                    detailRequest.getEquipmentId(), null, currentTime, null, null
            );

            // 8. 转换为响应数据
            ChargeDeviceDetailResponseData responseData = convertToDeviceDetail(result);

            log.info("查询充电终端详情成功, operatorId: {}, equipmentId: {}", request.getOperatorId(), result.getConnectorId());
            return buildSuccessResponse(responseData, thirdPartyInfo);

        } catch (Exception e) {
            log.error("处理query_charge_device_detail请求异常", e);
            return buildErrorResponse(500, "系统错误", null);
        }
    }

    /**
     * 转换充电站信息为详情响应（从AppletStationDetailVO转换）
     */
    private ChargeStationDetailResponseData convertToStationDetail(AppletStationDetailVO result) {
        ChargeStationDetailResponseData detail = new ChargeStationDetailResponseData();
        detail.setStationId(result.getStationId());
        detail.setStationName(result.getStationName());
        detail.setTips(result.getTips());
        detail.setDistance(result.getDistance());
        detail.setAddress(result.getAddress());
        detail.setLongitude(result.getLongitude());
        detail.setLatitude(result.getLatitude());
        detail.setPictures(result.getPictures());
        detail.setCurrentPrice(result.getCurrentPrice());
        detail.setCurrentPeriod(result.getCurrentPeriod());
        detail.setOriginalPrice(result.getOriginalPrice());
        detail.setPeriodFlag(result.getPeriodFlag());
        detail.setIdleCount(result.getIdleCount());
        detail.setOccupiedCount(result.getOccupiedCount());
        detail.setOfflineCount(result.getOfflineCount());
        detail.setBusinessHours(result.getBusinessHours());
        detail.setServiceProvider(result.getServiceProvider());
        detail.setInvoiceProvider(result.getInvoiceProvider());
        detail.setCustomerServiceHotline(result.getCustomerServiceHotline());

        // 转换充电终端列表
        if (result.getConnectorList() != null) {
            List<ChargeStationDetailResponseData.ConnectorInfoVO> connectorVOList = result.getConnectorList().stream()
                    .map(connector -> {
                        ChargeStationDetailResponseData.ConnectorInfoVO vo = new ChargeStationDetailResponseData.ConnectorInfoVO();
                        vo.setConnectorId(connector.getConnectorId());
                        vo.setConnectorName(connector.getConnectorName());
                        vo.setEquipmentType(connector.getEquipmentType());
                        vo.setConnectorCode(connector.getConnectorCode());
                        vo.setStatus(connector.getStatus());
                        vo.setStatusName(connector.getStatusName());
                        return vo;
                    })
                    .collect(Collectors.toList());
            detail.setConnectorList(connectorVOList);
        }

        return detail;
    }

    /**
     * 转换充电站信息为列表项
     */
    private ChargeStationListResponseData.StationItem convertToStationItem(StationInfoVO stationInfoVO) {
        ChargeStationListResponseData.StationItem item = new ChargeStationListResponseData.StationItem();
        item.setStationId(stationInfoVO.getStationId());
        item.setStationName(stationInfoVO.getStationName());
        item.setTips(stationInfoVO.getTips());
        item.setDistance(stationInfoVO.getDistance());
        item.setFastCharging(stationInfoVO.getFastCharging());
        item.setSlowCharging(stationInfoVO.getSlowCharging());
        item.setPeakValue(stationInfoVO.getPeakValue());
        item.setPeakTime(stationInfoVO.getPeakTime());
        item.setPeriodFlag(stationInfoVO.getPeriodFlag());
        item.setPlatformPrice(stationInfoVO.getPlatformPrice());
        return item;
    }

    /**
     * 转换充电设备信息为详情响应（从AppletConnectorDetailVO转换）
     */
    private ChargeDeviceDetailResponseData convertToDeviceDetail(AppletConnectorDetailVO connectorDetail) {
        ChargeDeviceDetailResponseData detail = new ChargeDeviceDetailResponseData();
        detail.setConnectorId(connectorDetail.getConnectorId());
        detail.setConnectorCode(connectorDetail.getConnectorCode());
        detail.setConnectorName(connectorDetail.getConnectorName());
        detail.setStationId(connectorDetail.getStationId());
        detail.setStationName(connectorDetail.getStationName());
        detail.setStationAddress(connectorDetail.getStationAddress());
        detail.setEquipmentId(connectorDetail.getEquipmentId());
        detail.setEquipmentCode(connectorDetail.getEquipmentCode());
        detail.setEquipmentName(connectorDetail.getEquipmentName());
        detail.setEquipmentType(connectorDetail.getEquipmentType());
        detail.setEquipmentTypeName(connectorDetail.getEquipmentTypeName());
        detail.setParkNo(connectorDetail.getParkNo());
        detail.setStatus(connectorDetail.getStatus());
        detail.setStatusName(connectorDetail.getStatusName());
        detail.setConnectorType(connectorDetail.getConnectorType());
        detail.setConnectorTypeName(connectorDetail.getConnectorTypeName());
        detail.setVoltageUpperLimits(connectorDetail.getVoltageUpperLimits());
        detail.setVoltageLowerLimits(connectorDetail.getVoltageLowerLimits());
        detail.setCurrent(connectorDetail.getCurrent());
        detail.setPower(connectorDetail.getPower());
        detail.setNationalStandard(connectorDetail.getNationalStandard());
        detail.setNationalStandardName(connectorDetail.getNationalStandardName());
        detail.setCurrentPrice(connectorDetail.getCurrentPrice());
        detail.setPeriodFlag(connectorDetail.getPeriodFlag());
        detail.setCurrentPeriodDesc(connectorDetail.getCurrentPeriodDesc());
        detail.setParkingTips(connectorDetail.getParkingTips());
        return detail;
    }

}
