package com.njcn.product.event.transientes.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.enums.common.LogEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.event.file.pojo.dto.WaveDataDTO;
import com.njcn.product.event.devcie.mapper.PqLineMapper;
import com.njcn.product.event.devcie.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.event.devcie.pojo.po.PqLine;
import com.njcn.product.event.devcie.pojo.po.PqsDeptsline;
import com.njcn.product.event.devcie.service.PqsDeptslineService;
import com.njcn.product.event.transientes.mapper.PqUserLedgerMapper;
import com.njcn.product.event.transientes.mapper.PqUserLineAssMapper;
import com.njcn.product.event.transientes.pojo.param.MonitorTerminalParam;
import com.njcn.product.event.transientes.pojo.param.SimulationMsgParam;
import com.njcn.product.event.transientes.pojo.po.*;
import com.njcn.product.event.transientes.service.*;
import com.njcn.product.event.transientes.service.impl.MsgEventInfoServiceImpl;
import com.njcn.product.event.transientes.websocket.WebSocketServer;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.web.controller.BaseController;
import com.njcn.web.utils.HttpResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.njcn.product.event.transientes.pojo.constant.RedisConstant.REDIS_DEPT_INDEX;

/**
 * @Author: cdf
 * @CreateTime: 2025-06-23
 * @Description:
 */
@Api(tags = "暂降接收")
@RequestMapping("accept")
@RestController
@RequiredArgsConstructor
@Slf4j
public class EventGateController extends BaseController {
    private final MsgEventInfoServiceImpl msgEventInfoServiceImpl;
    private final PqUserLineAssMapper pqUserLineAssMapper;
    private final PqUserLedgerMapper pqUserLedgerMapper;
    @Value("${SYS_TYPE_ZT}")
    private String sysTypeZt;

    private final WebSocketServer webSocketServer;

    private final PqsDeptslineService pqsDeptslineService;

    private final PqsDeptsService pqsDeptsService;

    private final PqsUserService pqsUserService;

    private final PqsUsersetService pqsUsersetService;

    private final PqLineMapper pqLineMapper;

    private final EventGateService eventGateService;

    private final MsgEventConfigService msgEventConfigService;

    private final MsgEventInfoService msgEventInfoService;

    private final RedisUtil redisUtil;


    @OperateInfo
    @GetMapping("/eventMsg")
    @ApiOperation("接收远程推送的暂态事件")
    @ApiImplicitParam(name = "eventMsg", value = "暂态事件json字符", required = true)
    public HttpResult<Object> eventMsg(@RequestParam("msg") String msg) {
        String methodDescribe = getMethodDescribe("eventMsg");
        log.info("收到前置推送暂降事件："+msg);

        JSONObject jsonObject;
        try {
            //下面一行代码正式环境需要放开
            jsonObject = new JSONObject(msg);
            //下面一行代码正式环境需要放开
            //jsonObject = test();

            if (msgEventConfigService.getEventType().contains(jsonObject.get("wavetype").toString())
                    && Float.parseFloat(jsonObject.get("eventvalue").toString()) <= msgEventConfigService.getEventValue()
                    && (Float.parseFloat(jsonObject.get("persisttime").toString())*1000) >= msgEventConfigService.getEventDuration()) {
                //过滤重要暂降事件
                Integer lineId = Integer.valueOf(jsonObject.get("lineid").toString());
                List<PqUserLineAssPO> assList = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().eq(PqUserLineAssPO::getLineIndex,lineId));

                String str ="/";
                if(CollUtil.isNotEmpty(assList)){
                   List<String> userIds = assList.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList());
                    List<PqUserLedgerPO> poList = pqUserLedgerMapper.selectList(new LambdaQueryWrapper<PqUserLedgerPO>().select(PqUserLedgerPO::getId,PqUserLedgerPO::getCustomerName).in(PqUserLedgerPO::getId,userIds));
                    str = poList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.joining(StrUtil.COMMA));
                }

                List<PqsDepts> deptsList = (List<PqsDepts>)redisUtil.getObjectByKey(REDIS_DEPT_INDEX+ StrUtil.DASHED+"AllDept");
                Map<String,PqsDepts> deptsMap = deptsList.stream().collect(Collectors.toMap(PqsDepts::getDeptsIndex,dept->dept));

                List<PqsDeptsline> deptslineList = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex,lineId).list();
                List<String> deptIds = deptslineList.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toList());
                Set<String> set =getAllParentIdsWithChildrenBatch(deptIds,deptsMap);
                jsonObject.putOpt("objName",str);
                jsonObject.putOpt("dept", String.join(StrUtil.COMMA, set));

                webSocketServer.sendMessageToAll(jsonObject.toString());
            }

        } catch (Exception e) {
            e.printStackTrace();
            log.error("暂降json格式异常!{}", e.getMessage());
        }
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
    }

    public Set<String> getAllParentIdsRecursive(String deptId, Map<String, PqsDepts> deptMap, Set<String> result) {
        if (deptId == null || result.contains(deptId)) {
            return result;
        }

        result.add(deptId); // 添加当前ID
        PqsDepts dept = deptMap.get(deptId);
        if (dept != null && dept.getParentnodeid() != null) {
            getAllParentIdsRecursive(dept.getParentnodeid(), deptMap, result); // 递归处理父节点
        }
        return result;
    }

    // 批量处理入口方法
    public Set<String> getAllParentIdsWithChildrenBatch(Collection<String> deptIds, Map<String, PqsDepts> deptMap) {
        Set<String> result = new HashSet<>();
        for (String deptId : deptIds) {
            getAllParentIdsRecursive(deptId, deptMap, result);
        }
        return result;
    }

    @OperateInfo
    @GetMapping("/testEvent")
    @ApiOperation("接收远程推送的暂态事件")
    public HttpResult<Object> testEvent() {
        String methodDescribe = getMethodDescribe("testEvent");
        log.info("模拟测试发送暂降事件-------------------------");

        JSONObject jsonObject;
        try {
            //下面一行代码正式环境需要放开
            jsonObject = test();

            if (msgEventConfigService.getEventType().contains(jsonObject.get("wavetype").toString()) &&Float.parseFloat(jsonObject.get("eventvalue").toString()) <= msgEventConfigService.getEventValue()) {
                webSocketServer.sendMessageToAll(jsonObject.toString());

                //开始发送短信
                try {
                    sendMessage(jsonObject);
                }catch (Exception e){
                    log.error("短信组装发送失败!失败原因{}",e.getMessage());
                }

            }

        } catch (Exception e) {
            log.error("暂降json格式异常!{}", e.getMessage());
        }
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
    }


    //测试模拟，正式环境删除
    private PqsEventdetail createEvent(JSONObject jsonObject, LocalDateTime now) {
        PqsEventdetail pqsEventdetail = new PqsEventdetail();
        pqsEventdetail.setEventdetailIndex(jsonObject.get("eventdetail_index").toString());
        pqsEventdetail.setLineid(Integer.valueOf(jsonObject.get("lineid").toString()));
        pqsEventdetail.setTimeid(now);
        pqsEventdetail.setMs(new BigDecimal(jsonObject.get("ms").toString()));
        pqsEventdetail.setWavetype(Integer.valueOf(jsonObject.get("wavetype").toString()));
        pqsEventdetail.setPersisttime(Double.valueOf(jsonObject.get("persisttime").toString()));
        pqsEventdetail.setEventvalue(Double.valueOf(jsonObject.get("eventvalue").toString()));
        pqsEventdetail.setEventreason(jsonObject.get("eventreason").toString());
        pqsEventdetail.setEventtype(jsonObject.get("eventtype").toString());

        return pqsEventdetail;
    }

    //测试模拟，正式环境删除
    private JSONObject test() {
        /*----------------------------------------------------------------------------------------*/
        //以下部分为测试数据后续删除
        List<PqLine> pqLineList = pqLineMapper.selectList(new LambdaQueryWrapper<>());
        List<Integer> lineList = pqLineList.stream().map(PqLine::getLineIndex).collect(Collectors.toList());
        List<LedgerBaseInfoDTO> baseInfoDTOList = pqLineMapper.getBaseLineInfo(lineList);
        Map<Integer, LedgerBaseInfoDTO> map = baseInfoDTOList.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity()));

        Random random = new Random();
        Integer lineId = lineList.get(random.nextInt(lineList.size()));
        LedgerBaseInfoDTO dto = map.get(lineId);

        LocalDateTime now = LocalDateTime.now();
        String timeStr = DateUtil.format(now, DatePattern.NORM_DATETIME_PATTERN);
        Long ms = (long) random.nextInt(999);

        Integer[] temArr = new Integer[]{1, 3};
        Integer wave = random.nextInt(2);


        Double per =  (double)random.nextInt(5000);

        double minV = 0.1;
        double maxV = 0.9;
        Double eventValue = minV + (maxV - minV) * Math.random();

        String id = IdUtil.simpleUUID();

        JSONObject tem = new JSONObject();
        tem.set("eventdetail_index", id);
        tem.set("lineid", lineId.toString());
        tem.set("timeid", timeStr);
        tem.set("ms", ms.toString());
        tem.set("wavetype", temArr[wave]);
        tem.set("persisttime", per.toString());
        tem.set("eventvalue", eventValue);
        tem.set("eventreason", "97a56e0f-b546-4c1e-b27c-52463fc1d82f");
        tem.set("eventtype", "676683a0-7f80-43e6-8df8-bea8ed235d67");
        tem.set("gdname", "测试供电公司");
        tem.set("bdname", dto.getStationName());
        tem.set("pointname", dto.getLineName());

     /*   PqsEventdetail pqsEventdetail = createEvent(tem, now);
        if (msgEventConfigService.getEventType().contains(tem.get("wavetype").toString())) {
            webSocketServer.sendMessageToAll(tem.toString());
        }
        pqsEventdetailService.save(pqsEventdetail);*/
        /*----------------------------------------------------------------------------------------*/

        return tem;
    }


    @OperateInfo(info = LogEnum.BUSINESS_COMMON)
    @PostMapping("/getTransientAnalyseWave")
    @ApiOperation("暂态事件波形分析")
    public HttpResult<WaveDataDTO> getTransientAnalyseWave(@RequestBody MonitorTerminalParam param) {
        String methodDescribe = getMethodDescribe("getTransientAnalyseWave");
        WaveDataDTO wave = eventGateService.getTransientAnalyseWave(param);
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, wave, methodDescribe);
    }


    @OperateInfo(info = LogEnum.BUSINESS_COMMON)
    @PostMapping("/simulationSend")
    @ApiOperation("模拟发送短信")
    public HttpResult<WaveDataDTO> simulationSend(@RequestBody @Validated SimulationMsgParam param) {
        String methodDescribe = getMethodDescribe("simulationSend");
        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
    }


    private void sendMessage(JSONObject jsonObject) throws Exception{
        Integer lineId = Integer.valueOf(jsonObject.get("lineid").toString());
        List<PqsDeptsline> pqLineDept = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex, lineId).eq(PqsDeptsline::getSystype, sysTypeZt).list();
        Set<String> deptIds = pqLineDept.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toSet());
        Set<String> resultIds = getAllParentDeptIds(deptIds);

        List<PqsUserSet> pqsUserSetList = pqsUsersetService.lambdaQuery().eq(PqsUserSet::getIsNotice, 1).in(PqsUserSet::getDeptsIndex, resultIds).list();
        if (CollUtil.isEmpty(pqsUserSetList)) {
            //当前事件未找到用户信息，判断为不需要发送短信用户
            return;
        }
        List<PqsUser> pqsUserList = pqsUserService.lambdaQuery().select(PqsUser::getUserIndex,PqsUser::getPhone,PqsUser::getName).in(PqsUser::getUserIndex, pqsUserSetList.stream().map(PqsUserSet::getUserIndex).collect(Collectors.toList())).list();
        List<String> userIds = pqsUserList.stream().map(PqsUser::getUserIndex).collect(Collectors.toList());
        List<PqsUserSet> poList = pqsUserSetList.stream().filter(it -> userIds.contains(it.getUserIndex())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(poList)) {
            StringBuilder stringBuilder = new StringBuilder(jsonObject.get("timeid").toString());
            List<LedgerBaseInfoDTO> list = pqLineMapper.getBaseLineInfo(Stream.of(lineId).collect(Collectors.toList()));
            LedgerBaseInfoDTO ledgerBaseInfoDTO = list.get(0);
            BigDecimal bigDecimal = new BigDecimal(jsonObject.get("eventvalue").toString()).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
            stringBuilder.append(".").append(jsonObject.get("ms").toString()).append(", ").append(ledgerBaseInfoDTO.getStationName()).append(ledgerBaseInfoDTO.getLineName())
                    .append("发生暂降事件,事件特征幅值").append(bigDecimal).append("%,持续时间:").append(jsonObject.get("persisttime").toString()).append("S");
            //TODO 发送短信
           // System.out.println(stringBuilder);

            List<MsgEventInfo> resultList = new ArrayList<>();
            for (PqsUser user : pqsUserList) {
                MsgEventInfo msgEventInfo = new MsgEventInfo();
                msgEventInfo.setEventIndex(jsonObject.get("eventdetail_index").toString());
                msgEventInfo.setMsgContent(stringBuilder.toString());
                msgEventInfo.setMsgIndex(IdUtil.simpleUUID());
                msgEventInfo.setPhone(user.getPhone());
                msgEventInfo.setSendResult(0);
                msgEventInfo.setUserId(user.getUserIndex());
                msgEventInfo.setUserName(user.getName());
                msgEventInfo.setIsHandle(0);
                msgEventInfo.setSendTime(LocalDateTime.now());
                resultList.add(msgEventInfo);
            }
            msgEventInfoService.saveBatch(resultList);
        }
    }

    /**
     * 获取远程短信平台token
     */
    private String apiToken() {

        return "token";
    }

    private boolean apiSend(){
        return false;
    }


    public Set<String> getAllParentDeptIds(Set<String> deptIds) {
        // 首次获取直接父级
        List<PqsDepts> allDeptList = pqsDeptsService.lambdaQuery().list();
        // 递归获取所有父级
        Set<String> result = recursivelyGetParentIds(deptIds, allDeptList);
        return result;
    }

    /**
     * 递归获取所有父级ID
     *
     * @param currentParentIds 当前层级的父级ID集合
     * @return 所有层级的父级ID集合
     */
    private Set<String> recursivelyGetParentIds(Set<String> currentParentIds, List<PqsDepts> allDeptList) {
        Set<String> result = new HashSet<>(currentParentIds);
        Set<String> nextLevelParentIds = new HashSet<>();
        List<PqsDepts> parentDeptList = allDeptList.stream().filter(it -> currentParentIds.contains(it.getDeptsIndex())).collect(Collectors.toList());
        for (PqsDepts pqsDepts : parentDeptList) {
            if (!pqsDepts.getParentnodeid().equals("0")) {
                nextLevelParentIds.add(pqsDepts.getParentnodeid());
            }
        }
        // 如果有更高层级的父级，继续递归
        if (!nextLevelParentIds.isEmpty()) {
            Set<String> deeperParentIds = recursivelyGetParentIds(nextLevelParentIds, allDeptList);
            result.addAll(deeperParentIds);
        }
        return result;
    }


}
