package com.centreproject.system.service.park.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.centreproject.common.constant.GuestConstants;
import com.centreproject.common.constant.KeyConstants;
import com.centreproject.common.utils.DateUtils;
import com.centreproject.common.websocket.MyWebSocketHandler;
import com.centreproject.system.domain.kpi.park.ParkTicketType;
import com.centreproject.system.domain.vo.ParkTicketTypeVo;
import com.centreproject.system.mapper.park.ParkTicketTypeMapper;
import com.centreproject.system.service.park.IParkTicketTypeService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * park ticket type service implementation
 * @author zhonglie.xu
 */
@Service
public class ParkTicketTypeServiceImpl extends ServiceImpl<ParkTicketTypeMapper, ParkTicketType>
        implements IParkTicketTypeService {
    private final Logger logger = LoggerFactory.getLogger(ParkTicketTypeServiceImpl.class);
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private ParkTicketTypeMapper mapper;
    @Autowired
    private MyWebSocketHandler myWebSocketHandler;
    /**
     * park ticket type
     *
     * @param parkCode park code
     * @return 园区门票
     */
    @Override
    public ParkTicketTypeVo getParkTicketType(String parkCode) {
        String redisKey = KeyConstants.PARK_TICKET_TYPE + DateUtils.getRiDate() +parkCode+ GuestConstants.LATEST_60_DAYS;

        // 1. 查缓存
        ParkTicketTypeVo cached = (ParkTicketTypeVo)redisTemplate.opsForValue().get(redisKey);
        if (null!=cached) {
            return cached;
        }
        // 带时区的获取当前日期
        LocalDate today = DateUtils.getNowLocalDate();

        LambdaQueryWrapper<ParkTicketType> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ParkTicketType::getStatisticsDate, today);
        wrapper.eq(ParkTicketType::getParkCode, parkCode);
        List<ParkTicketType> results = mapper.selectList(wrapper);
        ParkTicketTypeVo parkTicketTypeVo = new ParkTicketTypeVo();
        if(ObjectUtils.isNotEmpty(results)){
            // 2. 计算总票数
            BigDecimal totalTicket = results.stream()
                    .map(ParkTicketType::getMonthlySalesTotal)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            parkTicketTypeVo.setSales(totalTicket);
            parkTicketTypeVo.setLists(results);
            redisTemplate.opsForValue().set(redisKey, parkTicketTypeVo, 10, TimeUnit.MINUTES);
        }
        return parkTicketTypeVo;
    }


    @Scheduled(fixedRate = 30000) // 每30秒执行一次
    public void pushParkTicketTypeToRedis() {
        // 带时区的获取当前日期
        LocalDate today = DateUtils.getNowLocalDate();

        LambdaQueryWrapper<ParkTicketType> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ParkTicketType::getStatisticsDate, today);
        ParkTicketTypeVo parkTicketTypeVo = new ParkTicketTypeVo();
        List<ParkTicketType> results = mapper.selectList(wrapper);
        if(CollectionUtils.isNotEmpty(results)){
            Map<String, List<ParkTicketType>> map = results.stream().collect(Collectors.groupingBy(ParkTicketType::getParkCode));
            map.forEach((parkCode,parkTicketTypeList) -> {
                // 构建每个园区的独立消息
                BigDecimal totalTicket = parkTicketTypeList.stream()
                        .map(ParkTicketType::getMonthlySalesTotal)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                parkTicketTypeVo.setSales(totalTicket);
                parkTicketTypeVo.setLists(parkTicketTypeList);
                Map<String, Object> message = new HashMap<>();
                message.put("module", KeyConstants.PARK_TICKET_TYPE+parkCode);
                message.put("data", parkTicketTypeVo);
                message.put("timestamp", System.currentTimeMillis());
                // 转换为JSON并推送
                String jsonData = JSON.toJSONString(message);
                myWebSocketHandler.broadcast(jsonData);
                logger.info("模块{}园区[{}]数据推送成功，数据:{}",KeyConstants.PARK_TICKET_TYPE, parkCode, jsonData);
            });
        }
    }
}
