package com.zd.laboratory.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.zd.common.core.domain.per.PerFun;
import com.zd.common.core.domain.per.PerPrefix;
import com.zd.common.core.utils.StringUtils;
import com.zd.common.core.utils.poi.ExcelUtil;
import com.zd.common.core.web.controller.BaseController;
import com.zd.common.core.web.domain.AjaxResult;
import com.zd.common.core.web.page.TableDataInfo;
import com.zd.common.log.annotation.Log;
import com.zd.common.log.enums.BusinessType;
import com.zd.common.redis.service.RedisService;
import com.zd.common.security.annotation.PreAuthorize;
import com.zd.laboratory.domain.*;
import com.zd.laboratory.domain.dto.LabRiskPlanDTO;
import com.zd.laboratory.domain.vo.LabSubjectVO;
import com.zd.laboratory.service.ILabHardwareService;
import com.zd.laboratory.service.ILabRiskPlanAbnormalLogService;
import com.zd.laboratory.service.ILabRiskPlanService;
import com.zd.laboratory.service.ILabSubjectService;
import com.zd.system.api.laboratory.domain.SensorFunctionStatus;
import com.zd.system.api.laboratory.domain.vo.SenseValVO;
import com.zd.system.api.laboratory.domain.vo.SubFunction;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 风险预案Controller
 *
 * @author zd
 * @date 2021-09-03
 */
@RestController
@RequestMapping("/plan")
@Api(tags = {"风险预案"})
public class LabRiskPlanController extends BaseController {
    @Autowired
    private ILabRiskPlanService labRiskPlanService;

    @Autowired
    private ILabRiskPlanAbnormalLogService labRiskPlanAbnormalLogService;

    @Autowired
    private ILabSubjectService labSubjectService;

    @Autowired
    private ILabHardwareService labHardwareService;

    @Autowired
    RedisService redisService;

    /**
     * 查询风险预案列表
     */
    @PreAuthorize(hasPermi = PerPrefix.LABORATORY_PLAN + PerFun.LIST)
    @GetMapping("/list")
    public TableDataInfo list(LabRiskPlanDTO labRiskPlan) {
        startPage();
        List<LabRiskPlanDTO> list = labRiskPlanService.selectLabRiskPlanStatisticList(labRiskPlan);
        return getDataTable(list);
    }

    /**
     * 导出风险预案列表
     */
    @PreAuthorize(hasPermi = PerPrefix.LABORATORY_PLAN + PerFun.EXPORT)
    @Log(title = "风险预案", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, LabRiskPlan labRiskPlan) throws IOException {
        List<LabRiskPlan> list = labRiskPlanService.selectLabRiskPlanList(labRiskPlan);
        ExcelUtil<LabRiskPlan> util = new ExcelUtil<LabRiskPlan>(LabRiskPlan.class);
        util.exportExcel(response, list, "风险预案数据");
    }

    /**
     * 获取风险预案详细信息
     */
    @PreAuthorize(hasPermi = PerPrefix.LABORATORY_PLAN + PerFun.QUERY)
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return AjaxResult.success(labRiskPlanService.selectLabRiskPlanById(id));
    }

    @PostMapping(value = "/getLabRiskPlanRepeat")
    public AjaxResult getLabRiskPlanRepeat(@RequestBody LabRiskPlan labRiskPlan) {
        Map<String,Object> map = labRiskPlanService.getLabRiskPlanRepeat(labRiskPlan);
        return AjaxResult.success(map);
    }

    /**
     * 新增风险预案
     */
    @PreAuthorize(hasPermi = PerPrefix.LABORATORY_PLAN + PerFun.ADD)
    @Log(title = "风险预案", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody LabRiskPlan labRiskPlan) {
        labRiskPlanService.insertLabRiskPlan(labRiskPlan);
        return success();
    }

    /**
     * 修改风险预案
     */
    @PreAuthorize(hasPermi = PerPrefix.LABORATORY_PLAN + PerFun.EDIT)
    @Log(title = "风险预案", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody LabRiskPlan labRiskPlan) {
        return toAjax(labRiskPlanService.updateLabRiskPlan(labRiskPlan));
    }

    /**
     * 获取预案关联实验室信息
     */
    @PostMapping(value = "/getLabRiskPlanJoinSub")
    public AjaxResult getLabRiskPlanJoinSub(@RequestBody LabRiskPlan labRiskPlan) {
        if(labRiskPlan.getAllSelect()){
            LabSubjectVO labSubject = new LabSubjectVO();
            List<LabSubject> list = labSubjectService.getUserRoleBySub(labSubject);
            List <LabRiskPlanjoinsub> labRiskPlanjoinsubList = new ArrayList<>();
            for(LabSubject subject:list){
                LabRiskPlanjoinsub labRiskPlanjoinsub = new LabRiskPlanjoinsub();
                labRiskPlanjoinsub.setSubjectId(subject.getId());
                labRiskPlanjoinsubList.add(labRiskPlanjoinsub);
            }
            labRiskPlan.setLabRiskPlanjoinsubList(labRiskPlanjoinsubList);
        }
        Map<String,Object> map = labRiskPlanService.getLabRiskPlanJoinSub(labRiskPlan);
        return AjaxResult.success(map);
    }

    /**
     * 预案关联实验室提交
     */
    @Log(title = "预案关联实验室提交", businessType = BusinessType.INSERT)
    @PreAuthorize(hasPermi = PerPrefix.LABORATORY_PLANJOIN + PerFun.EDIT)
    @PostMapping("/riskPlanJoinSub")
    public AjaxResult riskPlanJoinSub(@RequestBody LabRiskPlan labRiskPlan) {
        if(labRiskPlan.getAllSelect()){
            LabSubjectVO labSubject = new LabSubjectVO();
            List<LabSubject> list = labSubjectService.getUserRoleBySub(labSubject);
            List <LabRiskPlanjoinsub> labRiskPlanjoinsubList = new ArrayList<>();
            for(LabSubject subject:list){
                LabRiskPlanjoinsub labRiskPlanjoinsub = new LabRiskPlanjoinsub();
                labRiskPlanjoinsub.setSubjectId(subject.getId());
                labRiskPlanjoinsubList.add(labRiskPlanjoinsub);
            }
            labRiskPlan.setLabRiskPlanjoinsubList(labRiskPlanjoinsubList);
        }
        labRiskPlanService.riskPlanJoinSub(labRiskPlan);
        return success();
    }

    /**
     * 删除风险预案
     */
    @PreAuthorize(hasPermi = PerPrefix.LABORATORY_PLAN + PerFun.REMOVE)
    @Log(title = "风险预案", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(labRiskPlanService.deleteLabRiskPlanByIds(ids));
    }


    /**
     * 执行传感器对应的风险预案
     */
    @Log(title = "执行传感器对应的风险预案")
    @PostMapping("/triggerRiskPlan")
    public AjaxResult triggerRiskPlan(@RequestBody SubFunction <SensorFunctionStatus> subFunction) {
        try {
            int flag=1;
            //如果实验室ID为空 通过设备ID查询绑定实验室ID
            if(StringUtils.isNull(subFunction.getSubId())){
                if(subFunction.getFunctionStatuses().size()>0){
                    Long subId = labHardwareService.querySubIdByNum(subFunction.getFunctionStatuses().get(0).getHardwareNum());
                    if(StringUtils.isNull(subId)){
                        return toAjax(flag);
                    }
                    subFunction.setSubId(subId);
                    //这里整理了一下，如果是关于火焰报警的，那么其他传感器上报数据将不再执行匹配预案，直到手动关闭了火焰预案，那么才能继续执行对应预案。
                    Optional.ofNullable(subFunction.getFunctionStatuses()).orElseGet(Collections::emptyList)
                            .stream()
                            .filter(a->"huoyan".equals(a.getFunNum()))
                            .forEach(a->{
                                //没有火焰预警的缓存信息，则执行智能预警方法，否则不执行， 需要手动关闭火焰预警
                                if(redisService.getCacheObject("subjectByHuoyan"+subFunction.getSubId())==null){
//                                    redisService.setCacheObject("subjectByHuoyan"+subFunction.getSubId(), subFunction.getSubId());
                                    labRiskPlanService.triggerRiskPlan(subFunction);
                                }
                            });
                }
            }
            if(redisService.getCacheObject("subjectByHuoyan"+subFunction.getSubId())==null){
                labRiskPlanService.triggerRiskPlan(subFunction);
            }
            return toAjax(flag);
        }catch (Exception e){
            e.printStackTrace();
        }
        return toAjax(500);
    }

    /**
     * 手动关闭风险预案
     */
    @Log(title = "手动关闭风险预案")
    @PostMapping("/closeRiskPlan")
    public AjaxResult closeRiskPlan(@RequestBody LabRiskPlanAbnormalGroup labRiskPlanAbnormalGroup) {
        try {
            LabRiskPlanAbnormalLog labRiskPlanAbnormalLog = new LabRiskPlanAbnormalLog();
            labRiskPlanAbnormalLog.setGroupId(labRiskPlanAbnormalGroup.getId());
            List<LabRiskPlanAbnormalLog> logList = labRiskPlanAbnormalLogService.selectLabRiskPlanAbnormalLogOrderByList(labRiskPlanAbnormalLog);
            Optional.ofNullable(logList).orElseGet(Collections::emptyList).stream().filter(a->a.getRiskStatus()==1).forEach(a->{
                SubFunction <SensorFunctionStatus> subFunction = new SubFunction <>();
                subFunction.setSubId(a.getSubjectId());
                List<SensorFunctionStatus> sensorList = JSONArray.parseArray(a.getSensorJson(),SensorFunctionStatus.class);
                subFunction.setFunctionStatuses(sensorList);
                //删除火焰报警的redis验证，这样其他传感器上报预案就能执行了
                redisService.deleteObject("subjectByHuoyan"+subFunction.getSubId());
                //关闭预案
                labRiskPlanService.closeRiskPlan(subFunction);
            });
            return toAjax(1);
        }catch (Exception e){
            e.printStackTrace();
        }
        return toAjax(500);
    }

    /**
     * 预案触发的时候，关闭所有实验室下的电源
     */
    @Log(title = "预案触发的时候，关闭所有实验室下的电源")
    @PostMapping("/closePower/{subId}")
    public AjaxResult closePower(@PathVariable("subId") Long subId) {
        return toAjax(labRiskPlanService.closePower(subId));
    }


    /**
     * 删除风险预案绑定的实验室
     */
    @PreAuthorize(hasPermi = PerPrefix.LABORATORY_PLAN + PerFun.REMOVE)
    @Log(title = "风险预案", businessType = BusinessType.DELETE)
    @DeleteMapping("/removeByPlanJoinSub")
    public AjaxResult removeByPlanJoinSub(@RequestBody LabRiskPlanjoinsub labRiskPlanjoinsub) {
        return toAjax(labRiskPlanService.removeByPlanJoinSub(labRiskPlanjoinsub));
    }

    /**
     * 查询风险预案列表（下拉列表）
     */
    @GetMapping("/getNoauthList")
    public AjaxResult getNoauthList(LabRiskPlanDTO labRiskPlan) {
        List<LabRiskPlanDTO> list = labRiskPlanService.selectLabRiskPlanStatisticList(labRiskPlan);
        return AjaxResult.success(list);
    }
}
