package com.xzzn.ems.service.impl;

import com.alibaba.fastjson2.JSON;
import com.xzzn.common.constant.RedisKeyConstants;
import com.xzzn.common.core.domain.entity.SysUser;
import com.xzzn.common.core.redis.RedisCache;
import com.xzzn.common.enums.AlarmLevelStatus;
import com.xzzn.common.enums.AlarmStatus;
import com.xzzn.common.enums.TicketStatus;
import com.xzzn.common.utils.DateUtils;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsAlarmMatchData;
import com.xzzn.ems.domain.EmsAlarmRecords;
import com.xzzn.ems.domain.EmsTicket;
import com.xzzn.ems.domain.vo.AlarmRecordListRequestVo;
import com.xzzn.ems.domain.vo.AlarmRecordListResponseVo;
import com.xzzn.ems.mapper.EmsAlarmMatchDataMapper;
import com.xzzn.ems.mapper.EmsAlarmRecordsMapper;
import com.xzzn.ems.mapper.EmsTicketMapper;
import com.xzzn.ems.service.IEmsAlarmRecordsService;
import com.xzzn.system.mapper.SysUserMapper;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 告警记录Service业务层处理
 *
 * @author xzzn
 * @date 2025-06-29
 */
@Service
public class EmsAlarmRecordsServiceImpl implements IEmsAlarmRecordsService
{
    @Autowired
    private EmsAlarmRecordsMapper emsAlarmRecordsMapper;
    @Autowired
    private EmsTicketMapper emsTicketMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private RedisCache redisCache;

    private Map<String, String> alarmMap = new HashMap<String, String>() {{
        put("021_DDS_01", "PCS");
        put("021_FXX_01", "PCS01");
    }};
    @Autowired
    private EmsAlarmMatchDataMapper emsAlarmMatchDataMapper;

    /**
     * 查询告警记录
     *
     * @param id 告警记录主键
     * @return 告警记录
     */
    @Override
    public EmsAlarmRecords selectEmsAlarmRecordsById(Long id)
    {
        return emsAlarmRecordsMapper.selectEmsAlarmRecordsById(id);
    }

    /**
     * 查询告警记录列表
     *
     * @param emsAlarmRecords 告警记录
     * @return 告警记录
     */
    @Override
    public List<EmsAlarmRecords> selectEmsAlarmRecordsList(EmsAlarmRecords emsAlarmRecords)
    {
        return emsAlarmRecordsMapper.selectEmsAlarmRecordsList(emsAlarmRecords);
    }

    /**
     * 新增告警记录
     *
     * @param emsAlarmRecords 告警记录
     * @return 结果
     */
    @Override
    public int insertEmsAlarmRecords(EmsAlarmRecords emsAlarmRecords)
    {
        emsAlarmRecords.setCreateTime(DateUtils.getNowDate());
        return emsAlarmRecordsMapper.insertEmsAlarmRecords(emsAlarmRecords);
    }

    /**
     * 修改告警记录
     *
     * @param emsAlarmRecords 告警记录
     * @return 结果
     */
    @Override
    public int updateEmsAlarmRecords(EmsAlarmRecords emsAlarmRecords)
    {
        emsAlarmRecords.setUpdateTime(DateUtils.getNowDate());
        return emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);
    }

    /**
     * 批量删除告警记录
     *
     * @param ids 需要删除的告警记录主键
     * @return 结果
     */
    @Override
    public int deleteEmsAlarmRecordsByIds(Long[] ids)
    {
        return emsAlarmRecordsMapper.deleteEmsAlarmRecordsByIds(ids);
    }

    /**
     * 删除告警记录信息
     *
     * @param id 告警记录主键
     * @return 结果
     */
    @Override
    public int deleteEmsAlarmRecordsById(Long id)
    {
        return emsAlarmRecordsMapper.deleteEmsAlarmRecordsById(id);
    }

    @Override
    public List<AlarmRecordListResponseVo> getAlarmRecordDetailList(AlarmRecordListRequestVo requestVo) {
        return emsAlarmRecordsMapper.getAlarmRecordDetailList(requestVo);
    }

    @Override
    public String createTicketNo(Long id, Long userId) {
        String ticketNo = "";
        // 校验告警记录是否存在
        EmsAlarmRecords emsAlarmRecords = emsAlarmRecordsMapper.selectEmsAlarmRecordsById(id);
        if (emsAlarmRecords == null) {
            return "告警记录不存在";
        }
        // 工单号是否存在
        if (StringUtils.isNotEmpty(emsAlarmRecords.getTicketNo())) {
            return "工单号已存在";
        }
        // 随机生成工单：T+日期+6位随机
        ticketNo = createRandomTicketNo();
        // 更新告警表
        emsAlarmRecords.setTicketNo(ticketNo);
        emsAlarmRecords.setStatus(AlarmStatus.PROCESSING.getCode());
        emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);
        // 不存在-默认userId
        if (userId == null) {
            userId = 1L;
        }
        SysUser user = sysUserMapper.selectUserById(userId);
        // 插入工单表
        EmsTicket emsTicket = new EmsTicket();
        emsTicket.setTicketNo(ticketNo);
        emsTicket.setTitle("工单"+id.toString());
        emsTicket.setContent(emsAlarmRecords.getAlarmContent());
        emsTicket.setUserId(userId);
        emsTicket.setWorkUserId(userId);
        emsTicket.setStatus(Long.valueOf(TicketStatus.WAITING.getCode()));
        emsTicket.setCreateTime(DateUtils.getNowDate());
        emsTicket.setCreateBy(user.getUserName());
        emsTicket.setUpdateTime(DateUtils.getNowDate());
        emsTicket.setUpdateBy(user.getUserName());
        emsTicketMapper.insertEmsTicket(emsTicket);
        return ticketNo;
    }

    @Override
    public String closeAlarm(Long id, Long userId) {
        EmsAlarmRecords emsAlarmRecords = emsAlarmRecordsMapper.selectEmsAlarmRecordsById(id);
        if (emsAlarmRecords == null) {
            return "告警记录不存在";
        }
        if (AlarmStatus.DONE.getCode().equals(emsAlarmRecords.getStatus())) {
            return "告警已关闭";
        }
        emsAlarmRecords.setStatus(AlarmStatus.DONE.getCode());
        emsAlarmRecords.setAlarmEndTime(DateUtils.getNowDate());
        emsAlarmRecords.setUpdateTime(DateUtils.getNowDate());
        if (userId == null) {
            userId = 1L;
        }
        SysUser user = sysUserMapper.selectUserById(userId);
        emsAlarmRecords.setUpdateBy(user != null ? user.getUserName() : "system");
        emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);
        return "success";
    }

    // 订阅失败-增加告警
    @Override
    public void addSubFailedAlarmRecord(String topic) {
        EmsAlarmRecords emsAlarmRecords = new EmsAlarmRecords();
        String siteId = "";
        String deviceId = "";
        String content = "topic订阅失败";
        String status = AlarmLevelStatus.EMERGENCY.getCode();

        if (topic.startsWith("021_DDS")) {
            siteId = "021_DDS_01";
            deviceId = alarmMap.get("021_DDS_01");
        } else if (topic.startsWith("021_FXX")) {
            siteId = "021_FXX_01";
            deviceId = alarmMap.get("021_FXX_01");
        }
        // 先判断是否存在未处理的订阅失败告警
        emsAlarmRecords = redisCache.getCacheObject(RedisKeyConstants.TOPIC_FAILED_ALRAM_RECORD + siteId + "_" + deviceId);
        if (emsAlarmRecords != null) {
            return;
        }
        emsAlarmRecords = createAlarmAtPcs(siteId,deviceId,content,status);
        emsAlarmRecordsMapper.insertEmsAlarmRecords(emsAlarmRecords);

        // 存redis便于订阅成功后处理
        redisCache.setCacheObject(RedisKeyConstants.TOPIC_FAILED_ALRAM_RECORD + siteId + "_" + deviceId, emsAlarmRecords);
    }

    @Override
    public void checkFailedRecord(String topic) {
        String siteId = "";
        String deviceId = "";

        if (topic.startsWith("021_DDS")) {
            siteId = "021_DDS_01";
            deviceId = alarmMap.get("021_DDS_01");
        } else if (topic.startsWith("021_FXX")) {
            siteId = "021_FXX_01";
            deviceId = alarmMap.get("021_FXX_01");
        }
        EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(RedisKeyConstants.TOPIC_FAILED_ALRAM_RECORD + siteId + "_" + deviceId);
        if (emsAlarmRecords != null) {
            // 存在更新为已处理，并清除redis
            emsAlarmRecords.setStatus(AlarmStatus.DONE.getCode());
            emsAlarmRecords.setAlarmEndTime(new Date());
            emsAlarmRecords.setUpdateTime(DateUtils.getNowDate());
            emsAlarmRecords.setUpdateBy("system");
            emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);
        }
    }

    @Override
    public void addEmptyDataAlarmRecord(String siteId, String topicDevice) {
         String key = getRedisKeyForTopicEmptyAlarm(siteId, topicDevice);
         EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(key);
         if (emsAlarmRecords != null) {
             return;
         }
        emsAlarmRecords =  createAlarmAtPcs(siteId,topicDevice,"topic内没有数据",AlarmLevelStatus.GENERAL.getCode());
        emsAlarmRecordsMapper.insertEmsAlarmRecords(emsAlarmRecords);

        // 存redis-防止重复插入-有效期一天
        redisCache.setCacheObject(key, emsAlarmRecords,1, TimeUnit.DAYS);
    }

    private EmsAlarmRecords createAlarmAtPcs(String siteId, String deviceId,String content,String level) {
        EmsAlarmRecords emsAlarmRecords = new EmsAlarmRecords();
        emsAlarmRecords.setSiteId(siteId);
        emsAlarmRecords.setDeviceId(deviceId);
        emsAlarmRecords.setAlarmContent(content);
        emsAlarmRecords.setAlarmLevel(level);
        emsAlarmRecords.setAlarmStartTime(new Date());
        emsAlarmRecords.setStatus(AlarmStatus.WAITING.getCode());
        emsAlarmRecords.setDeviceType("TCP");
        emsAlarmRecords.setCreateBy("system");
        emsAlarmRecords.setCreateTime(new Date());
        return emsAlarmRecords;
    }

    @Override
    public void deleteEmptyDataAlarmRecord(String siteId, String topicDevice) {
        String key = getRedisKeyForTopicEmptyAlarm(siteId, topicDevice);
        EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(key);
        if (emsAlarmRecords == null) {
            return;
        }
        emsAlarmRecords.setStatus(AlarmStatus.DONE.getCode());
        emsAlarmRecords.setUpdateTime(new Date());
        emsAlarmRecords.setAlarmEndTime(new Date());
        emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);

        redisCache.deleteObject(key);
    }

    private String createRandomTicketNo() {
        String ticketNo = "";
        String nowDate = DateUtils.dateTime();
        ticketNo = "T" + nowDate + String.format("%06d", new Random().nextInt(1000000));
        return ticketNo;
    }


    @Override
    public void  initAlarmMatchInfo() {
        List<EmsAlarmMatchData> alarmPointList = emsAlarmMatchDataMapper.selectEmsAlarmMatchDataList(null);
        Map<String, EmsAlarmMatchData> resultMap = alarmPointList.stream()
                .collect(Collectors.toMap(
                        data->data.getSiteId()+"_"+data.getDeviceCategory()+"_"+data.getPoint(),
                        data->data,
                        (existing, replacement) -> replacement
                ));
        // 存redis
        redisCache.setCacheObject(RedisKeyConstants.ALARM_MATCH_INFO,resultMap, 1, TimeUnit.DAYS);
    }

    @Override
    public List<EmsAlarmRecords> getAllUnfinishedRecords(List<String> needUpdateKeys, String siteId, String deviceId) {
        return emsAlarmRecordsMapper.getAllUnfinishedRecords(needUpdateKeys,siteId,deviceId);
    }

    @Override
    public void batchProcessAlarmRecords(List<EmsAlarmRecords> recordsList) {
        emsAlarmRecordsMapper.batchUpsert(recordsList);
    }

    @Override
    public void updateRedisAlarmRecords(String siteId, String deviceId) {
        if (StringUtils.isEmpty(siteId) || StringUtils.isEmpty(deviceId)) {
            return;
        }
        String redisKey = RedisKeyConstants.LATEST_ALARM_RECORD + "_" + siteId +"_" + deviceId;
        List<EmsAlarmRecords> allDeviceRecords = emsAlarmRecordsMapper.getNeedPutRedisAlarm(siteId,deviceId);
        // 转Map
        Map<String, EmsAlarmRecords> newAlarms = allDeviceRecords.stream()
                .filter(a -> !AlarmStatus.DONE.getCode().equals(a.getStatus()))
                .collect(Collectors.toMap(EmsAlarmRecords::getAlarmPoint, a -> a));
        redisCache.setAllCacheMapValue(redisKey, newAlarms);
    }

    @Override
    public void dealSyncData(String content, String operateType) {
        if (StringUtils.isEmpty(content)) {
            return;
        }

        EmsAlarmRecords alarmRecords = JSON.parseObject(content, EmsAlarmRecords.class);
        switch(operateType) {
            case "INSERT":
                insertEmsAlarmRecords(alarmRecords);
                break;
            default:
                break;
        }
    }

    @Override
    public void addDeviceOfflineRecord(String siteId, String deviceId) {
        String key = getRedisKeyForModbusFailAlarm(siteId, deviceId);
        EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(key);
        if (emsAlarmRecords != null) {
            return;
        }
        emsAlarmRecords =  createAlarmAtPcs(siteId, deviceId,"modbus连接设备失败", AlarmLevelStatus.GENERAL.getCode());
        emsAlarmRecordsMapper.insertEmsAlarmRecords(emsAlarmRecords);

        // 存redis-防止重复插入-有效期一天
        redisCache.setCacheObject(key, emsAlarmRecords,1, TimeUnit.DAYS);
    }

    @Override
    public void deleteDeviceOfflineRecord(String siteId, String deviceId) {
        String key = getRedisKeyForModbusFailAlarm(siteId, deviceId);
        EmsAlarmRecords emsAlarmRecords = redisCache.getCacheObject(key);
        if (emsAlarmRecords == null) {
            return;
        }
        emsAlarmRecords.setStatus(AlarmStatus.DONE.getCode());
        emsAlarmRecords.setUpdateTime(new Date());
        emsAlarmRecords.setAlarmEndTime(new Date());
        emsAlarmRecordsMapper.updateEmsAlarmRecords(emsAlarmRecords);

        redisCache.deleteObject(key);
    }

    private String getRedisKeyForTopicEmptyAlarm(String siteId, String topicDevice) {

        return RedisKeyConstants.TOPIC_EMPTY_ALARM_RECORD + siteId + "_" + topicDevice;
    }

    private String getRedisKeyForModbusFailAlarm(String siteId, String deviceId) {

        return RedisKeyConstants.MODBUS_OFFLINE_ALARM_RECORD + siteId + "_" + deviceId;
    }

}
