package com.limap.core.screen.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.limap.common.core.redis.RedisCache;
import com.limap.common.utils.ali.iot.ClientUtil;
import com.limap.core.screen.domain.DeviceSensorData;
import com.limap.core.screen.mapper.DeviceSensorDataMapper;
import com.limap.core.screen.mapper.ScreenMapper;
import com.limap.core.screen.service.IScreenService;
import com.limap.core.screen.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author jjb
 */
@Service
@DS("test")
public class ScreenServiceImpl  implements IScreenService {

    @Resource
    private ScreenMapper screenMapper;
    @Resource
    private RedisCache redisCache;
    @Autowired
    private ClientUtil clientUtil;
    @Resource
    private DeviceSensorDataMapper deviceSensorDataMapper;

    @Override
//    @Cacheable(value = "getUserPonds",key = "#{userId}",unless ="#result?.size() == 0" )
    public List<PondVo> getUserPonds(Long userId) {
        String key = "getUserPonds:" + userId;
        if(redisCache.hasKey(key)){
            return (List<PondVo>)redisCache.getCacheObject(key);
        }
        List<PondVo> userPonds = screenMapper.getUserPonds(userId);
        if(userPonds != null && !userPonds.isEmpty()){
            redisCache.setCacheObject(key,userPonds,60, TimeUnit.MINUTES);
        }
        return userPonds;
    }

    @Override
    public List<AppEquipmentVo> getUserEquipments(Long userId, Long[] pondIds,String deviceType) {
        List<AppEquipmentVo> equipments = screenMapper.getUserEquipments(userId, pondIds,deviceType);
        if(equipments == null || equipments.isEmpty()){
            return Collections.emptyList();
        }
        equipments.forEach(e->{
            String iotId = e.getIotId();
            String key = "deviceOnline:status:" + iotId;
            if(redisCache.hasKey(key)){
                e.setOnline((Integer) redisCache.getCacheObject(iotId));
            }else{
                JSONObject statusObject = clientUtil.thingStatusGet(iotId);
                if(statusObject != null){
                    redisCache.setCacheObject(key,statusObject.getInteger("status"),2, TimeUnit.MINUTES);
                    e.setOnline(statusObject.getInteger("status"));
                }
            }
        });
        if(equipments.stream().anyMatch(e-> "2".equals(e.getDeviceType()))){
            equipments.stream().filter(e-> "2".equals(e.getDeviceType())).forEach(e->{
                e.setSwitches(dealControlSwitch(userId,e.getId()));
            });
        }
        return equipments;
    }

    @Override
    public List<AppEquipmentVo> getEquipmentsList(Long userId, Long[] pondIds, String deviceType) {
        List<AppEquipmentVo> equipments = screenMapper.getUserEquipments(userId, pondIds,deviceType);
        if(equipments == null || equipments.isEmpty()){
            return Collections.emptyList();
        }
        if(equipments.stream().anyMatch(e-> "2".equals(e.getDeviceType()))){
            equipments.stream().filter(e-> "2".equals(e.getDeviceType())).forEach(e->{
                e.setSwitches(dealControlSwitch(userId,e.getId()));
            });
        }
        return equipments;
    }

    @Override
    public AppEquipmentVo getEquipmentById(Long deviceId) {
        return screenMapper.getEquipmentById(deviceId,null);
    }

    @Override
    public AppEquipmentVo getEquipmentByDeviceNo(String deviceName) {
        return screenMapper.getEquipmentById(null,deviceName);
    }

    @Override
    public List<EquipmentHistory> getEquipmentHistory(Long userId, Long deviceId) {
        return getEquipmentHistory(1, deviceId);
    }

    @Override
    public List<EquipmentHistory> getEquipmentHistory(Integer days, Long deviceId) {
        if(days == null){
            days = 1;
        }
        String key = "getEquipmentHistory:" + deviceId + ":" + days;
        if(redisCache.hasKey(key)){
            return (List<EquipmentHistory>)redisCache.getCacheObject(key);
        }
        
        // 从 PostgreSQL 获取设备信息（获取 serialNum）
        AppEquipmentVo equipment = screenMapper.getEquipmentById(deviceId, null);
        if(equipment == null || equipment.getSerialNum() == null){
            return Collections.emptyList();
        }
        String serialNum = equipment.getSerialNum();
        
        // 计算时间范围
        LocalDateTime endTime = LocalDateTime.now();
        LocalDateTime startTime = endTime.minusDays(days);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        
        // 根据天数确定聚合间隔：1天-30分钟，3天-1小时，7天-3小时
        Integer intervalType;
        if(days <= 1){
            intervalType = 1; // 实时数据
        } else if(days <= 3){
            intervalType = 2; // 10min
        } else {
            intervalType = 3; // 30min
        }
        
        // 从 TDengine 查询历史数据
        List<DeviceSensorData> dataList = deviceSensorDataMapper.getHistoryDataList(
                serialNum,
                startTime.format(formatter),
                endTime.format(formatter),
                intervalType
        );
        
        // 转换为 EquipmentHistory
        List<EquipmentHistory> list = convertToEquipmentHistory(dataList);
        
        if(list != null && !list.isEmpty()){
            redisCache.setCacheObject(key, list, 30, TimeUnit.MINUTES);
        }
        return list;
    }
    
    /**
     * 将 DeviceSensorData 转换为 EquipmentHistory
     */
    private List<EquipmentHistory> convertToEquipmentHistory(List<DeviceSensorData> dataList) {
        if(dataList == null || dataList.isEmpty()){
            return Collections.emptyList();
        }
        
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
        
        return dataList.stream().map(data -> {
            EquipmentHistory history = new EquipmentHistory();
            
            // 解析时间字符串
            String timeStr = data.getTime();
            if(timeStr != null && !timeStr.isEmpty()){
                // TDengine 返回的时间格式可能是 "2024-01-15 08:30:00.000"
                timeStr = timeStr.split("\\.")[0]; // 去掉毫秒部分
                LocalDateTime dateTime = LocalDateTime.parse(timeStr, inputFormatter);
                history.setDay(dateTime.format(dayFormatter));
                history.setTime(dateTime.format(timeFormatter));
            }
            
            history.setDissolvedOxygen(data.getDissolvedOxygen());
            history.setTemperature(data.getTemperature());
            history.setSaturability(data.getSaturability());
            history.setPH(data.getPh());
            history.setSalinity(data.getSalinity());
            
            return history;
        }).collect(Collectors.toList());
    }

    @Override
    public List<WarnVo> getWarnList(Long userId,Integer pageNum,Integer pageSize) {
        List<WarnVo> warnList = screenMapper.getWarnList(userId, pageNum, pageSize);
        return warnList;
    }

    @Override
    public List<WarnVo> getWarnListByDevice(Long deviceId, Integer pageNum, Integer pageSize) {
        return screenMapper.getWarnListByDevice(deviceId, pageNum, pageSize);
    }

    @Override
    public long getWarnListCount(Long userId) {
        return screenMapper.getWarnListCount(userId);
    }

    @Override
    public long getWarnListCountByDevice(Long deviceId) {
        return screenMapper.getWarnListCountByDevice(deviceId);
    }

    private List<ControlSwitch> dealControlSwitch(Long userId, Long deviceId) {
        String key = "dealControlSwitch:" + userId + ":" +deviceId ;
        if(redisCache.hasKey(key)){
            return (List<ControlSwitch>)redisCache.getCacheObject(key);
        }
        List<ControlSwitch> controlSwitch = getControlSwitch(deviceId);
        List<PondVo> userPonds = getUserPonds(userId);
        if(userPonds != null && !userPonds.isEmpty()){
            Map<Long, String> pondMap = userPonds.stream().collect(Collectors.toMap(PondVo::getId, PondVo::getPondName));
            controlSwitch.stream().forEach(s -> {
                s.setPondName(pondMap.get(s.getPondId()));
            });
        }
        redisCache.setCacheObject(key,controlSwitch,2, TimeUnit.MINUTES);
        return controlSwitch;
    }

    @Override
    public List<ControlSwitch> getControlSwitch(Long deviceId) {
        String key = "getControlSwitch:" + (deviceId == null? "all" : deviceId);
        if(redisCache.hasKey(key)){
            return (List<ControlSwitch>)redisCache.getCacheObject(key);
        }
        List<ControlSwitch> controlSwitch = screenMapper.getControlSwitch(deviceId);
        if(controlSwitch!= null &&!controlSwitch.isEmpty()){
            redisCache.setCacheObject(key,controlSwitch,1, TimeUnit.MINUTES);
        }
        return controlSwitch;
    }

    @Override
    public List<CompareRequest> historyCompare(CompareSearchVo vo) {
        List<CompareRequest> result = new ArrayList<>();
        Long[] deviceIds = vo.getDeviceIds();
        Integer day = vo.getDay();
        for (Long deviceId : deviceIds) {
            String key = "historyCompare:" + deviceId + ":" + day;
            if(redisCache.hasKey(key)){
                result.add((CompareRequest)redisCache.getCacheObject(key));
            }else{
                // 从 TDengine 查询历史数据
                List<EquipmentHistory> list = getEquipmentHistory(day, deviceId);
                if(list != null && !list.isEmpty()){
                    CompareRequest compareRequest = new CompareRequest();
                    compareRequest.setDeviceId(deviceId);
                    compareRequest.setDeviceName(null);
                    compareRequest.setHistory(list);
                    result.add(compareRequest);
                    redisCache.setCacheObject(key, compareRequest, 30, TimeUnit.MINUTES);
                }
            }
        }
        return result;
    }

    /**
     * 按时间范围查询设备历史数据（从 TDengine）
     */
    public List<EquipmentHistory> getEquipmentHistoryByTimeRange(Long deviceId, String startTime, String endTime) {
        String key = "getEquipmentHistoryByTimeRange:" + deviceId + ":" + startTime + ":" + endTime;
        if(redisCache.hasKey(key)){
            return (List<EquipmentHistory>)redisCache.getCacheObject(key);
        }

        // 从 PostgreSQL 获取设备信息（获取 serialNum）
        AppEquipmentVo equipment = screenMapper.getEquipmentById(deviceId, null);
        if(equipment == null || equipment.getSerialNum() == null){
            return Collections.emptyList();
        }
        String serialNum = equipment.getSerialNum();

        // 从 TDengine 查询历史数据（原始数据，不聚合）
        List<DeviceSensorData> dataList = deviceSensorDataMapper.getHistoryDataList(
                serialNum,
                startTime,
                endTime,
                1  // intervalType = 1 表示原始数据
        );

        // 转换为 EquipmentHistory
        List<EquipmentHistory> list = convertToEquipmentHistory(dataList);

        if(list != null && !list.isEmpty()){
            redisCache.setCacheObject(key, list, 30, TimeUnit.MINUTES);
        }
        return list;
    }
}
