package com.weather.modules.weather.station.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.weather.common.constant.Constant;
import com.weather.common.page.PageData;
import com.weather.common.redis.RedisKeys;
import com.weather.common.redis.RedisUtils;
import com.weather.common.service.impl.CrudServiceImpl;
import com.weather.common.utils.ConvertUtils;
import com.weather.modules.security.user.SecurityUser;
import com.weather.modules.sys.service.SysDeptService;
import com.weather.modules.weather.station.dao.WeatherStationDao;
import com.weather.modules.weather.station.dto.WeatherStationDTO;
import com.weather.modules.weather.station.dto.WeatherStationInfoSimpleDto;
import com.weather.modules.weather.station.entity.WeatherStationEntity;
import com.weather.modules.weather.station.service.WeatherStationService;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 气象站点表
 *
 * @author Mark 123
 * @since 1.0.0 2026-03-05
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WeatherStationServiceImpl extends CrudServiceImpl<WeatherStationDao, WeatherStationEntity, WeatherStationDTO> implements WeatherStationService {
    private final SysDeptService sysDeptService;
    private final RedisUtils redisUtils;
    @Override
    public QueryWrapper<WeatherStationEntity> getWrapper(Map<String, Object> params) {
        String stationName = (String) params.get("stationName");
        String stationCode = (String) params.get("stationCode");

        QueryWrapper<WeatherStationEntity> wrapper = new QueryWrapper<>();
        wrapper.like(StrUtil.isNotBlank(stationName), "station_name", stationName);
        wrapper.like(StrUtil.isNotBlank(stationCode), "station_code", stationCode);
        return sysDeptService.limitedQueryScope(wrapper);
    }

    @Override
    public PageData<WeatherStationDTO> page(Map<String, Object> params) {
        IPage<WeatherStationEntity> page = baseDao.selectPage(
                getPage(params, Constant.CREATE_DATE, false),
                getWrapper(params)
        );

        return getPageData(page, WeatherStationDTO.class);

    }

    @Override
    public WeatherStationDTO getByStationCode(Long stationCode) {
        QueryWrapper<WeatherStationEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("station_code", stationCode);
        return ConvertUtils.sourceToTarget(baseDao.selectOne(wrapper),WeatherStationDTO.class);
    }

    @Override
    public Map<Long, WeatherStationDTO> getByStationCodes(Set<Long> stationCodes) {
        if (stationCodes == null || stationCodes.isEmpty()) {
            return Collections.emptyMap();
        }
        List<String> codeList = stationCodes.stream().map(String::valueOf).collect(Collectors.toList());
        QueryWrapper<WeatherStationEntity> wrapper = new QueryWrapper<>();
        wrapper.in("station_code", codeList);
        List<WeatherStationEntity> entities = baseDao.selectList(wrapper);
        return entities.stream()
                .collect(Collectors.toMap(
                        e -> Long.valueOf(e.getStationCode()),
                        e -> ConvertUtils.sourceToTarget(e, WeatherStationDTO.class),
                        (a, b) -> a));
    }

    /** 站点列表缓存有效期（小时），站点变更频率极低 */
    private static final long STATION_LIST_CACHE_HOURS = 2;

    @SuppressWarnings("unchecked")
    @Override
    public List<WeatherStationInfoSimpleDto> getStationByDeptId() {
        Long deptId = SecurityUser.getDeptId();
        String cacheKey = RedisKeys.getStationListKey(deptId != null ? deptId : 0L);

        // 命中缓存直接返回（Jackson 反序列化为 List<Map>，需校验元素类型）
        Object cached = redisUtils.get(cacheKey);
        if (cached instanceof List list) {
            if (!list.isEmpty()) {
                Object first = list.get(0);
                if (first instanceof WeatherStationInfoSimpleDto) {
                    return (List<WeatherStationInfoSimpleDto>) list;
                }
                // Jackson 反序列化后元素是 LinkedHashMap，转换回 DTO
                if (first instanceof Map) {
                    return (List<WeatherStationInfoSimpleDto>) list.stream()
                            .map(m -> BeanUtil.copyProperties(m, WeatherStationInfoSimpleDto.class))
                            .toList();
                }
            }
        }

        QueryWrapper<WeatherStationEntity> wrapper = new QueryWrapper<>();
        wrapper = sysDeptService.limitedQueryScope(wrapper);
        List<WeatherStationEntity> entities = baseDao.selectList(wrapper);
        List<WeatherStationInfoSimpleDto> result = BeanUtil.copyToList(entities, WeatherStationInfoSimpleDto.class);

        // 缓存结果，站点数据变更频率极低（2小时）
        redisUtils.set(cacheKey, result, RedisUtils.HOUR_ONE_EXPIRE * STATION_LIST_CACHE_HOURS);
        log.debug("站点列表缓存已更新，共 {} 条", result.size());
        return result;
    }

    @Override
    public List<WeatherStationInfoSimpleDto> getStationByStationName() {
        return List.of();
    }

    /** 清除站点列表缓存（站点增删改时调用） */
    private void invalidateStationCache() {
        redisUtils.deleteByPattern(RedisKeys.getStationListPattern());
        log.debug("站点列表缓存已清除");
    }

    @Override
    public boolean insert(WeatherStationEntity entity) {
        boolean result = super.insert(entity);
        invalidateStationCache();
        return result;
    }

    @Override
    public boolean updateById(WeatherStationEntity entity) {
        boolean result = super.updateById(entity);
        invalidateStationCache();
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long[] ids) {
        super.delete(ids);
        invalidateStationCache();
    }

}