package com.kym.service.admin.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.kym.common.utils.CommUtil;
import com.kym.common.utils.IDGenerator;
import com.kym.entity.admin.Station;
import com.kym.entity.admin.StationWhitelist;
import com.kym.entity.admin.StationWhitelistConfig;
import com.kym.entity.admin.vo.StationWhitelistConfigVo;
import com.kym.entity.common.RedisKeys;
import com.kym.mapper.admin.StationWhitelistConfigMapper;
import com.kym.service.admin.StationService;
import com.kym.service.admin.StationWhitelistConfigService;
import com.kym.service.admin.StationWhitelistLogService;
import com.kym.service.admin.StationWhitelistService;
import jakarta.annotation.PostConstruct;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@DS("db-admin")
public class StationWhitelistConfigServiceImpl extends MPJBaseServiceImpl<StationWhitelistConfigMapper, StationWhitelistConfig> implements StationWhitelistConfigService {

    private static final long CACHE_EXPIRE_HOURS = 24;
    private final IDGenerator idGenerator = new IDGenerator();
    private final StationWhitelistConfigMapper stationWhitelistConfigMapper;
    private final StationService stationService;
    private final StationWhitelistService stationWhitelistService;
    private final StationWhitelistLogService stationWhitelistLogService;
    private final StringRedisTemplate redisTemplate;

    public StationWhitelistConfigServiceImpl(StationWhitelistConfigMapper stationWhitelistConfigMapper,
                                              StationService stationService,
                                              StationWhitelistService stationWhitelistService,
                                              StationWhitelistLogService stationWhitelistLogService,
                                              StringRedisTemplate redisTemplate) {
        this.stationWhitelistConfigMapper = stationWhitelistConfigMapper;
        this.stationService = stationService;
        this.stationWhitelistService = stationWhitelistService;
        this.stationWhitelistLogService = stationWhitelistLogService;
        this.redisTemplate = redisTemplate;
    }

    @PostConstruct
    public void init() {
        DynamicDataSourceContextHolder.push("db-admin");
        refreshConfigCache();
        DynamicDataSourceContextHolder.poll();
    }

    @Override
    public List<StationWhitelistConfigVo> listConfig() {
        return stationWhitelistConfigMapper.selectJoinList(StationWhitelistConfigVo.class,
                new MPJLambdaWrapper<StationWhitelistConfig>()
                        .selectAll(StationWhitelistConfig.class)
                        .orderByDesc(StationWhitelistConfig::getCreateTime)
        );
    }

    @Override
    public StationWhitelistConfig getConfigByStationId(String stationId) {
        return lambdaQuery()
                .eq(StationWhitelistConfig::getStationId, stationId)
                .one();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateConfig(String stationId, Integer enabled) {
        CommUtil.assertsNonNull(stationId, "站点ID不能为空");

        Station station = stationService.lambdaQuery()
                .eq(Station::getStationId, stationId)
                .one();
        CommUtil.assertsNonNull(station, "站点不存在");

        StationWhitelistConfig config = getConfigByStationId(stationId);
        Long operatorId = StpUtil.getLoginIdAsLong();
        String operatorName = StpUtil.getSession().getString("mobilePhone");

        if (config == null) {
            config = new StationWhitelistConfig();
            config.setId(idGenerator.nextId());
            config.setStationId(stationId);
            config.setStationName(station.getStationName());
            config.setEnabled(enabled);
            config.setCreateBy(operatorId);
            save(config);
        } else {
            lambdaUpdate()
                    .set(StationWhitelistConfig::getEnabled, enabled)
                    .eq(StationWhitelistConfig::getStationId, stationId)
                    .update();
        }

        String key = RedisKeys.STATION_WHITELIST_CONFIG + stationId;
        redisTemplate.opsForValue().set(key, String.valueOf(enabled), CACHE_EXPIRE_HOURS, TimeUnit.HOURS);

        stationWhitelistLogService.logConfigChange(stationId, station.getStationName(), enabled, operatorId, operatorName);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteConfig(String stationId) {
        CommUtil.assertsNonNull(stationId, "站点ID不能为空");
        
        lambdaUpdate().eq(StationWhitelistConfig::getStationId, stationId).remove();
        
        // 删除该站点的所有白名单用户
        stationWhitelistService.lambdaUpdate()
                .eq(StationWhitelist::getStationId, stationId)
                .remove();
        
        String key = RedisKeys.STATION_WHITELIST_CONFIG + stationId;
        redisTemplate.delete(key);
        
        // 清除白名单用户缓存
        stationWhitelistService.refreshCache(stationId);
        
        Long operatorId = StpUtil.getLoginIdAsLong();
        String operatorName = StpUtil.getSession().getString("mobilePhone");
        // 这里可以记录日志，如果需要的话
    }

    @Override
    public boolean isWhitelistEnabled(String stationId) {
        String key = RedisKeys.STATION_WHITELIST_CONFIG + stationId;
        String value = redisTemplate.opsForValue().get(key);
        if (value != null) {
            return "1".equals(value);
        }
        StationWhitelistConfig config = getConfigByStationId(stationId);
        boolean enabled = config != null && config.getEnabled() == StationWhitelistConfig.ENABLED_是;
        redisTemplate.opsForValue().set(key, String.valueOf(enabled ? 1 : 0), CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
        return enabled;
    }

    @Override
    public void refreshConfigCache() {
        List<StationWhitelistConfig> list = list();
        for (StationWhitelistConfig config : list) {
            String key = RedisKeys.STATION_WHITELIST_CONFIG + config.getStationId();
            redisTemplate.opsForValue().set(key,
                    String.valueOf(config.getEnabled()),
                    CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
        }
    }
}
