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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.entity.DataDictionary;
import com.yeejoin.amos.boot.biz.common.service.impl.DataDictionaryServiceImpl;
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.elevator.api.dto.*;
import com.yeejoin.amos.boot.module.elevator.api.entity.AlertCalled;
import com.yeejoin.amos.boot.module.elevator.api.entity.AlertFormValue;
import com.yeejoin.amos.boot.module.elevator.api.entity.DispatchPaper;
import com.yeejoin.amos.boot.module.elevator.api.entity.DispatchTask;
import com.yeejoin.amos.boot.module.elevator.api.entity.RescueProcess;
import com.yeejoin.amos.boot.module.elevator.api.enums.DispatchPaperEnums;
import com.yeejoin.amos.boot.module.elevator.api.enums.SourcesInfoEnum;
import com.yeejoin.amos.boot.module.elevator.api.mapper.RescueProcessMapper;
import com.yeejoin.amos.boot.module.elevator.api.service.IRescueProcessService;
import com.yeejoin.amos.boot.module.elevator.biz.utils.BeanDtoVoUtils;
import com.yeejoin.amos.boot.module.elevator.flc.biz.service.impl.AlertFormRecordServiceImpl;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;

/**
 * 救援过程表服务实现类
 *
 * @author system_generator
 * @date 2021-08-03
 */
@Service
public class RescueProcessServiceImpl extends BaseService<RescueProcessDto,RescueProcess,RescueProcessMapper> implements IRescueProcessService {

    @Autowired
    DispatchPaperServiceImpl dispatchPaperServiceImpl;

    @Autowired
    private DataDictionaryServiceImpl iDataDictionaryService;

    @Autowired
    DispatchTaskServiceImpl dispatchTaskServiceImpl;

    @Autowired
    private AlertFormValueServiceImpl iAlertFormValueService;

    @Autowired
    RepairConsultServiceImpl repairConsultServiceImpl;

    @Autowired
    private AlertFormRecordServiceImpl alertFormRecordService;

    @Autowired
    AlertCalledServiceImpl iAlertCalledService;

    @Autowired
    RedisUtils redisUtils;
    /**
     * 分页查询
     */
    public Page<RescueProcessDto> queryForRescueProcessPage(Page<RescueProcessDto> page)   {
        return this.queryForPage(page, null, false);
    }

    /**
     * 列表查询 示例
     */
    public List<RescueProcessDto> queryForRescueProcessList()   {
        return this.queryForList("" , false);
    }

    @Override
    public RescueProcessDto getProcessByAlertId(Long alertId) {
        // 先通过id 查找过程表
        RescueProcessDto rescueProcessDto = new RescueProcessDto();
        QueryWrapper<RescueProcess> templateQueryWrapper = new QueryWrapper<>();
        templateQueryWrapper.eq("alert_id",alertId);
        RescueProcess rescueProcess = this.getOne(templateQueryWrapper);
        if(rescueProcess == null) {
            rescueProcess = new RescueProcess();
            rescueProcess.setAlertId(alertId);
            this.save(rescueProcess);
        }
        Bean.toModel(rescueProcess, rescueProcessDto);
        // 到达时长 不超过30分钟为否，超过为是
        // 到达时长 救援响应人员到达时间—救援派遣成功时间
        //判断是否存在到达时间
        Date dispatchTime  = rescueProcessDto.getDispatchTime();
        Date arriveTime = rescueProcessDto.getArriveTime();
        Date rescueTime = rescueProcessDto.getRescueTime();
        if(arriveTime != null && dispatchTime != null) {
                Long arriveTimes = arriveTime.getTime() - dispatchTime.getTime(); // 相差毫秒数
                rescueProcessDto.setIsTimeout(arriveTimes < 1800000 ? false : true);
        }
        // 救援时长  用到达时间减去派遣时间
        if(dispatchTime != null && arriveTime != null) {
            String hms = DateUtils.getTimeDiffString(arriveTime, dispatchTime);
            rescueProcessDto.setArriveUseTime(hms);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        if(dispatchTime != null)  rescueProcessDto.setDispatchTimeStr(sdf.format(dispatchTime));
        if(arriveTime != null)  rescueProcessDto.setArriveTimeStr(sdf.format(arriveTime));
        if(rescueTime != null)  rescueProcessDto.setRescueTimeStr(sdf.format(rescueTime));
        return rescueProcessDto;
    }

    @Transactional
    @Override
    public Boolean updateByAlertId(RescueProcessDto rescueProcessDto, AgencyUserModel sendUser) {
        QueryWrapper<RescueProcess> templateQueryWrapper = new QueryWrapper<>();
        templateQueryWrapper.eq("alert_id", rescueProcessDto.getAlertId());
        RescueProcess rescueProcess = this.getOne(templateQueryWrapper);
        if (rescueProcess == null)
            throw new BadRequest("救援过程信息未找到");
        if (rescueProcessDto.getDispatchByUser()) { // 手动更新了派遣信息为三级派遣
            // 判断是否存在派遣单 不存在先创建派遣单
            DispatchPaperFormDto dispatchPaperDto = dispatchPaperServiceImpl.selectDispatchPaperDtoByAlertId(rescueProcessDto.getAlertId());
            if (dispatchPaperDto == null || dispatchPaperDto.getDispatchPaper() == null) {
                QueryWrapper<DataDictionary> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("type", "JQLX").eq("name", "困人救援");
                DataDictionary alertCode = iDataDictionaryService.getOne(queryWrapper);
                dispatchPaperDto = dispatchPaperServiceImpl.createDispatchPaper(rescueProcessDto.getAlertId(), alertCode.getCode(), sendUser);
            }

            DispatchPaper dispatchPaper = dispatchPaperDto.getDispatchPaper();
            List<AlertFormValue> dynamicFormAlert = dispatchPaperDto.getDynamicFormAlert();
            // 创建派遣单
            DispatchTaskDto dispatchTaskDto = new DispatchTaskDto();
            dispatchTaskDto.setDispatchTime(rescueProcessDto.getDispatchTime());
            dispatchTaskDto.setOrgTypeCode(DispatchPaperEnums.getEnumByCode("levelThreeUnit").getId());
            dispatchTaskDto.setOrgType(DispatchPaperEnums.getEnumByCode("levelThreeUnit").getValue());
            dispatchTaskDto.setAlertId(rescueProcessDto.getAlertId());
            dispatchTaskDto.setResponseOrgName("119");
            dispatchTaskDto.setResponseUserName("119");
            dispatchTaskDto.setResponseUserTel("119");
            dispatchTaskDto.setIsSaveTask(true);
            DispatchTask dispatchTask = BeanDtoVoUtils.convert(dispatchTaskDto, DispatchTask.class);
            dispatchTask.setPaperId(dispatchPaper.getSequenceNbr());
            Boolean flag = dispatchTaskServiceImpl.save(dispatchTask);
            if (flag) { // 创建好派遣任务单以后根据任务单类型修改派遣单信息
                if (dispatchPaper.getRepairOrgId() != null) { // 已经派遣过调派
                    throw new BadRequest("已经派遣过其他力量调派");
                } else {
                    dispatchPaper.setRepairOrgId("-1");
                    dispatchPaper.setRepairOrgCreditCode("119");
                    dispatchPaper.setRepairOrgTaskId(dispatchTask.getSequenceNbr());
                    // 修改动态字段
                    dynamicFormAlert.stream().forEach(alertFormValue -> {
                        if (alertFormValue.getFieldCode().equals("dispatch_status")) {
                            alertFormValue.setFieldValue(DispatchPaperEnums.hasDispatched.getValue());
                            alertFormValue.setFieldValueCode(DispatchPaperEnums.hasDispatched.getId());
                        } else if (alertFormValue.getFieldCode().equals("response_level")) {
                            alertFormValue.setFieldValue(DispatchPaperEnums.levelThreeUnit.getValue());
                            alertFormValue.setFieldValueCode(DispatchPaperEnums.levelThreeUnit.getId());
                            // 响应级别反馈给警情
                            LambdaUpdateWrapper<AlertCalled> updateWrapper = new LambdaUpdateWrapper<>();
                            updateWrapper.eq(AlertCalled::getSequenceNbr,dispatchTask.getAlertId());
                            updateWrapper.set(AlertCalled::getResponseLevel,DispatchPaperEnums.levelThreeUnit.getValue());
                            iAlertCalledService.update(updateWrapper);
                        }
                    });
                }
                //  更新派遣单
                dispatchPaperServiceImpl.updateById(dispatchPaper);
                // 保存动态表单数据
                iAlertFormValueService.updateBatchById(dynamicFormAlert);
                // 记录日志
                repairConsultServiceImpl.saveRepairConsultByAlertIdType(dispatchTask.getAlertId(),"PQ", dispatchTask.getSequenceNbr(),sendUser);
            }
        } else {
            if (Boolean.TRUE.equals(rescueProcessDto.getCasualtiesStatus())){
               try {
                   AlertCalledFormDto calledFormDto = iAlertCalledService.getAlertCalledFormDto(rescueProcessDto.getAlertId());
                   List<FormValue> dynamicFormAlert = calledFormDto.getDynamicFormAlert();
                   HashMap<String, String> formMap = new HashMap<>();
                   dynamicFormAlert.forEach(x->formMap.put(x.getKey(),x.getValue()));
                   if (!formMap.get("injured_num").equals(rescueProcessDto.getCasualtiesInfo()) || !formMap.get("die_num").equals(rescueProcessDto.getDieNum())){
                       //更新动态表单
                       updateMessage(rescueProcessDto, "injured_num");
                       updateMessage(rescueProcessDto, "die_num");
                       //更新警情历史记录表
                       saveAlertFormRecord(rescueProcessDto, calledFormDto, formMap);
                   }
               }catch (Exception e){
                   e.printStackTrace();
               }
                redisUtils.del(RedisKey.TZS_ALERTCALLED_ID+rescueProcessDto.getAlertId());
            }
            rescueProcessDto.setDispatchTime(null);
            rescueProcessDto.setDispatchStatus(null);
            rescueProcessDto.setDispatchUserId(null);
            rescueProcessDto.setDispatchUserName(null);
        }
        boolean arriveByUser = rescueProcessDto.getArriveByUser();
        boolean saveByUser = rescueProcessDto.getSaveByUser();
        if(!arriveByUser) { // 非手动反馈不更新
            rescueProcessDto.setArriveTime(null);
            rescueProcessDto.setArriveFeedbackCode(null);
            rescueProcessDto.setArriveFeedbackType(null);
            rescueProcessDto.setArriveStatus(null);
            rescueProcessDto.setArriveUserId(null);
            rescueProcessDto.setArriveUserName(null);
        }
        if(!saveByUser) {
            rescueProcessDto.setRescueTime(null);
            rescueProcessDto.setRescueFeedbackCode(null);
            rescueProcessDto.setRescueFeedbackType(null);
            rescueProcessDto.setRescueStatus(null);
            rescueProcessDto.setRescueUserId(null);
            rescueProcessDto.setRescueUserName(null);
        }
        rescueProcessDto.setSequenceNbr(rescueProcess.getSequenceNbr());
        rescueProcessDto.setRecDate(rescueProcess.getRecDate());
        rescueProcessDto.setRecUserId(rescueProcess.getRecUserId());
        rescueProcessDto.setRecUserName(rescueProcess.getRecUserName());
        rescueProcess = BeanDtoVoUtils.convert(rescueProcessDto, RescueProcess.class);
        Boolean flag =this.updateById(rescueProcess);
        if(arriveByUser) { // 手动到达



            DispatchPaperFormDto dispatchPaperDto = dispatchPaperServiceImpl.selectDispatchPaperDtoByAlertId(rescueProcessDto.getAlertId());
            if (dispatchPaperDto == null || dispatchPaperDto.getDispatchPaper() == null) {
                throw new BadRequest("派遣单信息未找到");
            }
            DispatchPaper dispatchPaper = dispatchPaperDto.getDispatchPaper();
            dispatchPaper.setArriveTime(rescueProcessDto.getArriveTime());
            dispatchPaper.setArriveFeedbackCode(rescueProcessDto.getArriveFeedbackCode());
            dispatchPaper.setArriveFeedbackType(rescueProcessDto.getArriveFeedbackType());
            //  更新派遣单
            dispatchPaperServiceImpl.updateById(dispatchPaper);
            // 如果存在三级响应id 则默认三级响应 否则为使用单位
            Long taskId = dispatchPaperDto.getDispatchPaper().getRepairOrgTaskId();
            if(taskId == null) {
                taskId =  dispatchPaperDto.getDispatchPaper().getUseOrgTaskId();
            }
            if(taskId == null) {
                throw new BadRequest("派遣任务单信息未找到");
            }
             // 更新派遣到达时间
            dispatchTaskServiceImpl.update(new LambdaUpdateWrapper<DispatchTask>().eq(DispatchTask::getSequenceNbr,taskId).set(DispatchTask::getArriveTime,rescueProcessDto.getArriveTime()));
            repairConsultServiceImpl.saveRepairConsultByAlertIdType( rescueProcessDto.getAlertId(),"DD",taskId,sendUser); //保存接警日志
        }
        if(saveByUser) { // 手动救援
            DispatchPaperFormDto dispatchPaperDto = dispatchPaperServiceImpl.selectDispatchPaperDtoByAlertId(rescueProcessDto.getAlertId());
            if (dispatchPaperDto == null || dispatchPaperDto.getDispatchPaper() == null) {
                throw new BadRequest("派遣单信息未找到");
            }
            // 如果存在三级响应id 则默认三级响应 否则为使用单位
            Long taskId = dispatchPaperDto.getDispatchPaper().getRepairOrgTaskId();
            if(taskId == null) {
                taskId =  dispatchPaperDto.getDispatchPaper().getUseOrgTaskId();
            }
            if(taskId == null) {
                throw new BadRequest("派遣任务单信息未找到");
            }
            DispatchPaper dispatchPaper = dispatchPaperDto.getDispatchPaper();
            dispatchPaper.setSaveTime(rescueProcessDto.getRescueTime());
            //  更新派遣单
            // 更新派遣救援时间
            dispatchTaskServiceImpl.update(new LambdaUpdateWrapper<DispatchTask>().eq(DispatchTask::getSequenceNbr,taskId).set(DispatchTask::getSaveTime,rescueProcessDto.getRescueTime()));
            dispatchPaperServiceImpl.updateById(dispatchPaper);
            repairConsultServiceImpl.saveRepairConsultByAlertIdType(rescueProcessDto.getAlertId(),"JC",taskId,sendUser); //保存接警日志
        }

        return flag;
    }

    private void saveAlertFormRecord(RescueProcessDto rescueProcessDto, AlertCalledFormDto calledFormDto, HashMap<String, String> formMap) throws ParseException {
        AlertCalledDto alertCalledDto = calledFormDto.getAlertCalledDto();
        AlertFormRecordDto alertFormRecordDto = new AlertFormRecordDto();
        alertFormRecordDto.setAlertCalledId(rescueProcessDto.getAlertId());
        alertFormRecordDto.setAlertTypeCode(alertCalledDto.getAlarmTypeCode());
        alertFormRecordDto.setName(alertCalledDto.getEmergencyPerson());
        alertFormRecordDto.setPhone(alertCalledDto.getEmergencyCall());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        alertFormRecordDto.setTrappedTime(sdf.parse(formMap.getOrDefault("trapped_time",new Date().toString())));
        alertFormRecordDto.setTrappedNum(Integer.valueOf(formMap.getOrDefault("trapped_num","0")));
        alertFormRecordDto.setTrappedFloorNum(Integer.parseInt(formMap.getOrDefault("trapped_floor_num","0")));
        int injuredNumBefore = Integer.parseInt(formMap.getOrDefault("injured_num", "0"));
        int dieNumBefore = Integer.parseInt(formMap.getOrDefault("die_num", "0"));
        alertFormRecordDto.setInjuredNum(Optional.ofNullable(rescueProcessDto.getCasualtiesInfo()).map(Integer::valueOf).orElse(injuredNumBefore));
        alertFormRecordDto.setDieNum(Optional.ofNullable(rescueProcessDto.getDieNum()).map(Integer::valueOf).orElse(dieNumBefore));
        alertFormRecordDto.setSourcesInfo(SourcesInfoEnum.Process.getCode().toString());
        alertFormRecordDto.setIsLight("是".equals(formMap.getOrDefault("is_light", "是"))? 1 : 0);
        alertFormRecordService.saveAlertFormRecord(alertFormRecordDto);
    }

    private void updateMessage(RescueProcessDto rescueProcessDto, String fieldCode){
        LambdaQueryWrapper<AlertFormValue> lambda = new QueryWrapper<AlertFormValue>().lambda();
        lambda.eq(AlertFormValue::getAlertCalledId, rescueProcessDto.getAlertId());
        lambda.eq(AlertFormValue::getFieldCode, fieldCode);
        List<AlertFormValue> alertFormValues = iAlertFormValueService.getBaseMapper().selectList(lambda);
        AlertFormValue alertFormValue = alertFormValues.get(0);
        if ("die_num".equals(fieldCode)){
            alertFormValue.setFieldValue(rescueProcessDto.getDieNum());
        }else {
            alertFormValue.setFieldValue(rescueProcessDto.getCasualtiesInfo());
        }
        iAlertFormValueService.updateById(alertFormValue);
    }
    @Override
    public Boolean updateByAlertId(RescueProcessDto rescueProcessDto) {
        QueryWrapper<RescueProcess> templateQueryWrapper = new QueryWrapper<>();
        templateQueryWrapper.eq("alert_id", rescueProcessDto.getAlertId());
        RescueProcess rescueProcess = this.getOne(templateQueryWrapper);
        if (rescueProcess == null)
            throw new BadRequest("救援过程信息未找到");
        rescueProcess = BeanDtoVoUtils.convert(rescueProcessDto, RescueProcess.class);
        Boolean flag =this.updateById(rescueProcess);
        return flag;
    }
}