package com.yeejoin.amos.boot.module.tzs.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.yeejoin.amos.boot.biz.common.utils.DateUtils;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.tzs.api.dto.AlertCalledDto;
import com.yeejoin.amos.boot.module.tzs.api.dto.AlertCalledFormDto;
import com.yeejoin.amos.boot.module.tzs.api.dto.AlertCalledObjsDto;
import com.yeejoin.amos.boot.module.tzs.api.dto.AlertCalledQueryDto;
import com.yeejoin.amos.boot.module.tzs.api.dto.FormValue;
import com.yeejoin.amos.boot.module.tzs.api.entity.AlertCalled;
import com.yeejoin.amos.boot.module.tzs.api.entity.AlertFormValue;
import com.yeejoin.amos.boot.module.tzs.api.entity.Elevator;
import com.yeejoin.amos.boot.module.tzs.api.enums.AlertStageEnums;
import com.yeejoin.amos.boot.module.tzs.api.enums.DispatchPaperEnums;
import com.yeejoin.amos.boot.module.tzs.api.mapper.AlertCalledMapper;
import com.yeejoin.amos.boot.module.tzs.api.service.IAlertCalledService;
import com.yeejoin.amos.boot.module.tzs.biz.utils.BeanDtoVoUtils;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.core.rdbms.annotation.Condition;
import org.typroject.tyboot.core.rdbms.annotation.Operator;
import org.typroject.tyboot.core.rdbms.service.BaseService;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 警情接警填报记录服务实现类
 *
 * @author litw
 * @date 2021-08-03
 */
@Service
public class AlertCalledServiceImpl extends BaseService<AlertCalledDto,AlertCalled,AlertCalledMapper> implements IAlertCalledService {

    @Autowired
    RedisUtils redisUtils;

    @Value("${redis.cache.failure.time}")
    private long time;

    @Autowired
    private AlertFormValueServiceImpl iAlertFormValueService;

    @Autowired
    TemplateServiceImpl templateService;

    @Autowired
    private ESAlertCalledService eSAlertCalledService;

    @Autowired
    private ElevatorServiceImpl iElevatorService;

    @Autowired
    AlertCalledMapper alertCalledMapper;

    @Autowired
    RescueProcessServiceImpl rescueProcessServiceImpl;

    @Autowired
    RepairConsultServiceImpl repairConsultServiceImpl;

    private final Logger logger = LogManager.getLogger(AlertCalledServiceImpl.class);


    @Override
    public Object selectAlertCalledById(Long id) {
        if(redisUtils.hasKey(RedisKey.TZS_ALERTCALLED_ID+id)){
            Object obj= redisUtils.get(RedisKey.TZS_ALERTCALLED_ID+id);
            return obj;
        }else{
            // 警情基本信息
            AlertCalled alertCalled = this.getById(id);
            LambdaQueryWrapper<AlertFormValue> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(AlertFormValue::getAlertCalledId, id);
            // 警情动态表单数据
            List<AlertFormValue> list = iAlertFormValueService.list(queryWrapper);
            List<FormValue> formValue = new ArrayList<FormValue>();
            if(list!=null&&list.size()>0) {
                for (AlertFormValue alertFormValue : list) {
                    FormValue value = new FormValue(alertFormValue.getFieldCode(), alertFormValue.getFieldName(), "text", alertFormValue.getFieldValue(),alertFormValue.getBlock());
                    formValue.add(value);
                }
            }
            AlertCalledDto alertCalledDto = BeanDtoVoUtils.convert(alertCalled,AlertCalledDto.class);
            LambdaQueryWrapper<Elevator> elevatorQueryWrapper = new LambdaQueryWrapper<>();
            elevatorQueryWrapper.eq(Elevator::getRescueCode, alertCalled.getDeviceId());
            elevatorQueryWrapper.eq(Elevator::getRegisterCode, alertCalled.getRegistrationCode());
            Elevator elevator =  iElevatorService.getOne(elevatorQueryWrapper);
            if(null !=  elevator) {
                alertCalledDto.setAddress(elevator.getAddress());
                alertCalledDto.setProvince(elevator.getProvince());
                alertCalledDto.setCity(elevator.getCity());
                alertCalledDto.setDistrict(elevator.getDistrict());
                alertCalledDto.setUseStatus(elevator.getUseStatus());
                alertCalledDto.setUseSiteCategory(elevator.getUseSiteCategory());
                alertCalledDto.setUseUnit(elevator.getUseUnit());
                alertCalledDto.setRegionCode(elevator.getRegionCode());
            }
            AlertCalledFormDto alertCalledFormVo = new AlertCalledFormDto(alertCalledDto, formValue);

            redisUtils.set(RedisKey.TZS_ALERTCALLED_ID+id, JSON.toJSON(alertCalledFormVo),time);
            return alertCalledFormVo;
        }
    }

    @Override
    public AlertCalledFormDto selectAlertCalledByIdNoCache(Long id) {
        // 警情基本信息
        AlertCalled alertCalled = this.getById(id);
        LambdaQueryWrapper<AlertFormValue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AlertFormValue::getAlertCalledId, id);
        // 警情动态表单数据
        List<AlertFormValue> list = iAlertFormValueService.list(queryWrapper);
        List<FormValue> formValue = new ArrayList<FormValue>();
        if(list!=null&&list.size()>0) {
            for (AlertFormValue alertFormValue : list) {
                FormValue value = new FormValue(alertFormValue.getFieldCode(), alertFormValue.getFieldName(), "text", alertFormValue.getFieldValue(),alertFormValue.getBlock());
                formValue.add(value);
            }
        }
        AlertCalledDto alertCalledDto = BeanDtoVoUtils.convert(alertCalled,AlertCalledDto.class);
        LambdaQueryWrapper<Elevator> elevatorQueryWrapper = new LambdaQueryWrapper<>();
        elevatorQueryWrapper.eq(Elevator::getRescueCode, alertCalled.getDeviceId());
        elevatorQueryWrapper.eq(Elevator::getRegisterCode, alertCalled.getRegistrationCode());
        Elevator elevator =  iElevatorService.getOne(elevatorQueryWrapper);
        if(null !=  elevator) {
            alertCalledDto.setAddress(elevator.getAddress());
            alertCalledDto.setProvince(elevator.getProvince());
            alertCalledDto.setCity(elevator.getCity());
            alertCalledDto.setDistrict(elevator.getDistrict());
            alertCalledDto.setUseStatus(elevator.getUseStatus());
            alertCalledDto.setUseSiteCategory(elevator.getUseSiteCategory());
            alertCalledDto.setUseUnit(elevator.getUseUnit());
            alertCalledDto.setRegionCode(elevator.getRegionCode());
        }
        AlertCalledFormDto alertCalledFormVo = new AlertCalledFormDto(alertCalledDto, formValue);
        return alertCalledFormVo;
    }

    @Override
    public Page<AlertCalledQueryDto> queryAlertListByQueryDto(IPage<AlertCalledQueryDto> page,
                                                              @Condition(Operator.like) String workOrderNumber,
                                                              @Condition(Operator.like) String creator,
                                                              @Condition(Operator.like) String emergency,
                                                              @Condition(Operator.gt) String emergencyTimeStart,
                                                              @Condition(Operator.lt) String emergencyTimeEnd,
                                                              @Condition(Operator.like) String emergencyCall,
                                                              @Condition(Operator.like) String deviceId,
                                                              @Condition(Operator.like) String elevatorAddress,
                                                              @Condition(Operator.eq) String alertType,
                                                              @Condition(Operator.eq) String alertSource,
                                                              @Condition(Operator.eq) String alertStage,
                                                              @Condition(Operator.eq) String alertStatus
                                                              ) {

        Page<List<AlertCalledQueryDto>>list = alertCalledMapper.queryAlertListByQueryDto(
                page,workOrderNumber,creator,emergency,emergencyTimeStart,
                emergencyTimeEnd,emergencyCall,deviceId,elevatorAddress,alertType,
                alertSource,alertStage,alertStatus,null);
        Page<AlertCalledQueryDto> page1 = new Page<>();
        List<AlertCalledQueryDto> resultDtoList = JSONArray.parseArray(JSONArray.toJSONString(list.getRecords()),AlertCalledQueryDto.class);
        page1.setCurrent(page.getCurrent());
        page1.setSize(page.getSize());
        page1.setTotal(list.getTotal());
        page1.setRecords(resultDtoList);
        return page1;
    }

    @Override
    public Boolean updateAlertStage(AlertCalledDto alertCalledVo, DispatchPaperEnums stage) {
        LambdaUpdateWrapper<AlertCalled> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(AlertCalled::getSequenceNbr,alertCalledVo.getSequenceNbr());
        updateWrapper.set(AlertCalled::getAlertStageCode,stage.getId());
        alertCalledVo.setAlertStage(stage.getValue());
        alertCalledVo.setAlertStageCode(stage.getId());
        updateWrapper.set(AlertCalled::getAlertStage,stage.getValue());
        if(stage == DispatchPaperEnums.reportorBack || stage == DispatchPaperEnums.complainantBack) {
            updateWrapper.set(AlertCalled::getAlertStatus,true);
            alertCalledVo.setAlertStatus(true);
        } else if(stage == DispatchPaperEnums.repaired  && alertCalledVo.getAlarmTypeCode().equals(AlertStageEnums.KRJY.getId())) {
            updateWrapper.set(AlertCalled::getAlertStatus,true);
            alertCalledVo.setAlertStatus(true);
        }
        Boolean flag = this.update(updateWrapper);
        if(flag) { //更新redis 和 es 信息
            try {
                redisUtils.del(RedisKey.TZS_ALERTCALLED_ID+alertCalledVo.getSequenceNbr());
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("删除redis失败:" + e.getMessage());
            }
            try {
                eSAlertCalledService.updateEsAlertCalled(alertCalledVo);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("更新es失败:" + e.getMessage());
            }
        }
        return this.update(updateWrapper);
    }


    /**
     *
     * <pre>
     * 保存警情信息
     * </pre>
     *
     * @param alertCalledObjsDto
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public AlertCalledObjsDto createAlertCalled(AlertCalledObjsDto alertCalledObjsDto, AgencyUserModel user) {
        try {
            // 警情基本信息

            AlertCalled alertCalled = BeanDtoVoUtils.convert(alertCalledObjsDto.getAlertCalledDto(),AlertCalled.class);

            alertCalled.setCallTime(DateUtils.longStr2Date(alertCalled.getCallTimeStr()));

            // 判断是否归并警情
            if (alertCalled.getFatherAlert() != null) {
                // 警情归并，设置当前警情状态为结束。
                alertCalled.setAlertStatus(true);
                alertCalled.setAlertStage(AlertStageEnums.JJ.getValue());
                alertCalled.setAlertStageCode(AlertStageEnums.JJ.getId());
                alertCalled.setType(AlertStageEnums.JQGB.getValue());
                alertCalled.setTypeCode(AlertStageEnums.JQGB.getId());
                this.save(alertCalled);
                // 动态表单
                List<AlertFormValue> alertFormValuelist = alertCalledObjsDto.getAlertFormValue();
                // 填充警情主键
                alertFormValuelist.stream().forEach(alertFormValue -> {
                    alertFormValue.setAlertCalledId(alertCalled.getSequenceNbr());
                    alertFormValue.setAlertTypeCode(alertCalled.getAlarmTypeCode());
                });
                // 保存动态表单数据
                iAlertFormValueService.saveBatch(alertFormValuelist);
                // 警情基本信息
                AlertCalled alertCalledFather = this.getById(alertCalled.getFatherAlert());
                alertCalledObjsDto.setAlertCalledDto(BeanDtoVoUtils.convert(alertCalledFather,AlertCalledDto.class));

            } else {
                // 警情报送
                // ****************************************************待确认开发
                alertCalled.setAlertStatus(false);
                alertCalled.setIsDelete(false);
                alertCalled.setAlertStage(AlertStageEnums.JJ.getValue());
                alertCalled.setAlertStageCode(AlertStageEnums.JJ.getId());
                alertCalled.setType(AlertStageEnums.JQCB.getValue());
                alertCalled.setTypeCode(AlertStageEnums.JQCB.getId());
                this.save(alertCalled);

                // 动态表单
                List<AlertFormValue> alertFormValuelist = alertCalledObjsDto.getAlertFormValue();
                // 填充警情主键
                alertFormValuelist.stream().forEach(alertFormValue -> {
                    alertFormValue.setAlertCalledId(alertCalled.getSequenceNbr());
                    alertFormValue.setAlertTypeCode(alertCalled.getAlarmTypeCode());
                });
                if(AlertStageEnums.KRJY.getId().equals(alertCalled.getAlarmTypeCode()) ) {
                    //困人救援创建警情时创建救援过程信息
                    rescueProcessServiceImpl.getProcessByAlertId(alertCalled.getSequenceNbr());
                }

                // 保存动态表单数据
                iAlertFormValueService.saveBatch(alertFormValuelist);
                alertCalledObjsDto.setAlertCalledDto(BeanDtoVoUtils.convert(alertCalled,AlertCalledDto.class));
                alertCalledObjsDto.setAlertFormValue(alertFormValuelist);
                //保存处置记录-接警
                repairConsultServiceImpl.saveRepairConsultByAlertIdType(alertCalled.getSequenceNbr(),AlertStageEnums.JJ.getCode(),null, user); //保存接警日志
            }

            /**
             * 同步保存ES
             */
            eSAlertCalledService.saveAlertCalledToES(alertCalled);

            return alertCalledObjsDto;
        } catch (Exception e) {
            logger.error("报送失败",e);
            throw new RuntimeException("报送失败，系统异常!");
        }
    }

    public Map<String, Object> getAlertInfoList(String beginDate, String endDate,String orgCode, String recUserId) {

        Map<String, Object> result = Maps.newHashMap();
        Map<String, Integer> statusCountMap = alertCalledMapper.queryAlertStatusCount(beginDate, endDate,orgCode,recUserId);

        result.put("calledCount",statusCountMap.get("calledCount"));
        result.put("majorAlertCount",statusCountMap.get("majorAlertCount"));
        result.put("sleepyIncidentCount",statusCountMap.get("sleepyIncidentCount"));
        result.put("faultRescueCount",statusCountMap.get("faultRescueCount"));
        result.put("suggestionsCount",statusCountMap.get("suggestionsCount"));

        return result;
    }

    public Map<String, Object> getNearlyInfo(String beginDate, String endDate,String orgCode, String recUserId) {

        Map<String, Object> result = Maps.newHashMap();
        List<Map<String, Integer>> statusCountMap = alertCalledMapper.queryNearlyCount(beginDate, endDate,orgCode,recUserId);
         for(int i = 0; i<statusCountMap.size();i++) {
             if(statusCountMap.get(i).size() > 1) {
                 result.put("dateTime"+i,statusCountMap.get(i).get("dateTime"));
                 result.put("majorAlertCount"+i,statusCountMap.get(i).get("majorAlertCount"));
             } else {
                 result.put("dateTime"+i,statusCountMap.get(i).get("dateTime"));
                 result.put("majorAlertCount"+i,0);
             }
         }
        return result;
    }

}