package com.kym.service.cache;

import cn.hutool.extra.spring.SpringUtil;
import com.kym.common.exception.BusinessException;
import com.kym.common.utils.CommUtil;
import com.kym.entity.common.RedisKeys;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author skyline
 * @description 缓存
 */
public enum KymCache {
    INSTANCE;

    /**
     * 短编号与设备信息映射
     */
    private static ConcurrentHashMap<String, String> SHORT_ID_TO_PRODUCT_KEY_AND_DEVICE_NAME_MAPPING = new ConcurrentHashMap<>();


    /**
     * 用户id与归属站点id映射
     *
     * @param map
     */
    public void putUserId2StationId(Map<Long, String> map) {
        map.forEach((k, v) -> KymCacheInjector.redisTemplate.opsForValue().set(RedisKeys.USER_ID_TO_STATION_ID + k, v));
    }

    /**
     * 通过消费用户id获取归属站点Id
     *
     * @param userId
     */
    public String getUserStationId(Long userId) {
        return KymCacheInjector.redisTemplate.opsForValue().get(RedisKeys.USER_ID_TO_STATION_ID + userId);
    }

    /**
     * 通过消费用户id获取归属站点Id
     *
     * @param userId
     */
    public String getUserStationName(Long userId) {
        return getStationNameById(getUserStationId(userId));
    }

    /**
     * 通过消费用户id获取站点商户投资者adminUserId
     *
     * @param userId
     */
    public Long getInvestorAdminUserIdByUserId(Long userId) {
        return getInvestorAdminUserIdByStationId(Objects.requireNonNull(KymCacheInjector.redisTemplate.opsForValue().get(RedisKeys.USER_ID_TO_STATION_ID + userId)));
    }

    /**
     * 站点id与商户id映射
     *
     * @param map
     */
    public void putStationId2InvestorAdminUserId(Map<String, String> map) {
        map.forEach((k, v) -> KymCacheInjector.redisTemplate.opsForValue().set(RedisKeys.STATION_ID_TO_INVESTOR_ADMIN_USER_ID + k, v));
    }

    /**
     * 站点id与站点名称映射
     *
     * @param map
     */
    public void putStationId2Name(Map<String, String> map) {
        map.forEach((k, v) -> KymCacheInjector.redisTemplate.opsForValue().set(RedisKeys.STATION_ID_TO_NAME + k, v));
    }

    /**
     * 通过站点id获取商户id
     *
     * @param stationId
     * @return
     */
    public Long getInvestorAdminUserIdByStationId(String stationId) {
        return Long.valueOf(Objects.requireNonNull(KymCacheInjector.redisTemplate.opsForValue().get(RedisKeys.STATION_ID_TO_INVESTOR_ADMIN_USER_ID + stationId)));
    }

    /**
     * 通过站点id获取站点名称
     *
     * @param stationId
     * @return
     */
    public String getStationNameById(String stationId) {
        return KymCacheInjector.redisTemplate.opsForValue().get(RedisKeys.STATION_ID_TO_NAME + stationId);
    }

    /**
     * 站点id与站点停车券链接
     *
     * @param map
     */
    public void putStationId2ParkingQrCodeUrl(Map<String, String> map) {
        map.forEach((k, v) -> KymCacheInjector.redisTemplate.opsForValue().set(RedisKeys.STATION_ID_TO_PARKING_QR_CODE_URL + k, v));
    }

    /**
     * 通过站点id获取站点停车券链接
     *
     * @param stationId
     * @return
     */
    public String getParkingQrCodeUrlByStationId(String stationId) {
        var url = KymCacheInjector.redisTemplate.opsForValue().get(RedisKeys.STATION_ID_TO_PARKING_QR_CODE_URL + stationId);
        return cleanNullBytes(url);
    }

    /**
     * 站点id与停车券最低消费金额
     */
    public void putStationId2ParkingCouponMinAmount(Map<String, Integer> map) {
        map.forEach((k, v) -> KymCacheInjector.redisTemplate.opsForValue().set(RedisKeys.STATION_ID_TO_PARKING_COUPON_MIN_AMOUNT + k, v.toString()));
    }

    /**
     * 通过站点id获取停车券最低消费金额（单位：分），未配置时返回默认600
     */
    public int getParkingCouponMinAmountByStationId(String stationId) {
        var v = KymCacheInjector.redisTemplate.opsForValue().get(RedisKeys.STATION_ID_TO_PARKING_COUPON_MIN_AMOUNT + stationId);
        if (CommUtil.isNotEmptyAndNull(v)) {
            return Integer.parseInt(v);
        }
        return 600;
    }


    /**
     * 运营平台账号（包含运营，投资者，物业等）对应有权限的站点
     *
     * @param map
     */
    public void putAdminUser2Stations(Map<Long, List<String>> map) {
        map.forEach((k, v) -> {
            String key = RedisKeys.ADMIN_USER_STATION_IDS + k;
            String[] values = v.toArray(new String[0]); // 优化数组创建方式，使用varargs来避免不必要的数组拷贝
            KymCacheInjector.redisTemplate.opsForSet().add(key, values);
        });
    }

    /**
     * 获取运营平台操作员有权限的站点ID
     *
     * @param adminUserId
     * @return
     */
    public List<String> getAdminUserStationIds(Long adminUserId) {
        return KymCacheInjector.redisTemplate.opsForSet().members(RedisKeys.ADMIN_USER_STATION_IDS + adminUserId).stream().toList();
    }


    /**
     * 缓存短编号和设备信息
     *
     * @param map
     */
    public void putWashShortId2ProductKeyAndDeviceName(Map<String, String> map) {
        map.forEach((k, v) -> KymCacheInjector.redisTemplate.opsForValue().set(RedisKeys.SHORT_ID_TO_PRODUCT_KEY_AND_DEVICE_NAME + k, v));
        SHORT_ID_TO_PRODUCT_KEY_AND_DEVICE_NAME_MAPPING.putAll(map);
    }


    /**
     * 缓存短编号与站点id映射
     *
     * @param map
     */
    public void putShortId2StationId(Map<String, String> map) {
        map.forEach((k, v) -> KymCacheInjector.redisTemplate.opsForValue().set(RedisKeys.SHORT_ID_TO_STATION_ID + k, v));
    }

    /**
     * 删除短编号与设备信息的映射缓存
     *
     * @param shortId
     */
    public void removeWashShortIdMapping(String shortId) {
        KymCacheInjector.redisTemplate.delete(RedisKeys.SHORT_ID_TO_PRODUCT_KEY_AND_DEVICE_NAME + shortId);
        SHORT_ID_TO_PRODUCT_KEY_AND_DEVICE_NAME_MAPPING.remove(shortId);
    }

    /**
     * 删除短编号与站点id的映射缓存
     *
     * @param shortId
     */
    public void removeShortId2StationId(String shortId) {
        KymCacheInjector.redisTemplate.delete(RedisKeys.SHORT_ID_TO_STATION_ID + shortId);
    }

    /**
     * 通过短编号获取站点id
     *
     * @param shortId
     * @return
     */
    public String gesStationIdByShortId(String shortId) {
        return KymCacheInjector.redisTemplate.opsForValue().get(RedisKeys.SHORT_ID_TO_STATION_ID + shortId);
    }

    /**
     * 通过短编号获取productKey和deviceName
     *
     * @param shortId
     * @return
     */
    public String[] getProductKeyAndDeviceNameByWashShortId(String shortId) {
        var res = new String[]{};
        var s = Objects.requireNonNull(KymCacheInjector.redisTemplate.opsForValue().get(RedisKeys.SHORT_ID_TO_PRODUCT_KEY_AND_DEVICE_NAME + shortId));
        if (CommUtil.isNotEmptyAndNull(s)) {
            res = s.split(",");
        }
        if (res.length != 2) {
            throw new BusinessException("设备信息异常");
        }
        return res;
    }

    /**
     * 通过productKey和deviceName获取设备短编号
     */
    public String getShortIdByProductKeyAndDeviceName(String productKey, String deviceName) {
        return SHORT_ID_TO_PRODUCT_KEY_AND_DEVICE_NAME_MAPPING.entrySet().stream().filter(entry -> (productKey + "," + deviceName).equals(entry.getValue())).map(Map.Entry::getKey).findFirst().orElse(null);
    }

    public void setParkingCouponCode(String code, String parkingCouponUrl, Long seconds) {
        KymCacheInjector.redisTemplate.opsForValue().set(RedisKeys.PARKING_COUPON_CODE + code, parkingCouponUrl, Duration.ofSeconds(seconds));
    }

    public String getParkingCouponUrl(String code) {
        var url = KymCacheInjector.redisTemplate.opsForValue().get(RedisKeys.PARKING_COUPON_CODE + code);
        return cleanNullBytes(url);
    }

    private static String cleanNullBytes(String value) {
        if (value == null || value.isEmpty()) {
            return value;
        }
        // 移除 NULL 字节及其之前的所有垃圾数据，只保留有效 URL
        int idx = value.indexOf("http");
        if (idx > 0) {
            return value.substring(idx);
        }
        return value;
    }


    @Component
    public static class KymCacheInjector {
        private static final StringRedisTemplate redisTemplate = SpringUtil.getBean(StringRedisTemplate.class);

    }
}
