package com.casic.missiles.modular.alarm.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.casic.missiles.core.application.context.AbstractPermissionContext;
import com.casic.missiles.core.application.enums.UserQueryEnum;
import com.casic.missiles.core.application.service.AbstractUserService;
import com.casic.missiles.core.datascope.DataScope;
import com.casic.missiles.core.util.EhcacheConstant;
import com.casic.missiles.modular.alarm.job.DelayJob;
import com.casic.missiles.modular.alarm.job.HandleAlarmJob;
import com.casic.missiles.modular.alarm.model.JobListParam;
import com.casic.missiles.modular.alarm.service.IAlarmJobService;
import com.casic.missiles.modular.system.dao.AlarmJobMapper;
import com.casic.missiles.modular.system.dao.AlarmRecordsMapper;
import com.casic.missiles.modular.system.dto.SelectDto;
import com.casic.missiles.modular.system.dto.UserClientView;
import com.casic.missiles.modular.system.model.AlarmJob;
import com.casic.missiles.modular.system.model.BusWellInfo;
import com.casic.missiles.modular.system.model.User;
import com.casic.missiles.modular.system.service.IBusWellInfoSupportService;
import com.casic.missiles.modular.system.util.PushList;
import com.casic.missiles.modular.system.util.WebSocket;
import com.casic.missiles.quartz.service.IQuartzManager;
import com.gexin.rp.sdk.base.IPushResult;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 报警工单表 服务实现类
 * </p>
 *
 * @author casic123
 * @since 2019-05-17
 */
@Service
@Slf4j
public class AlarmJobServiceImpl extends ServiceImpl<AlarmJobMapper, AlarmJob> implements IAlarmJobService {

    private static final Logger logger = LoggerFactory.getLogger(AlarmJobServiceImpl.class);

    @Value("${smartcity.leaderRoleName}")
    private String sLeader;
    @Value("${smartcity.memberRoleName}")
    private String sMember;
    @Value("${smartcity.appRoleName}")
    private String sApp;
    @Value("${smartcity.useOverTime}")
    private String useOverTime;

    @Resource
    private AlarmRecordsMapper alarmRecordsMapper;
    //    @Resource
//    private ICommonPermissionService permissionService;
    @Resource
    private AbstractPermissionContext iCommonUserService;
    @Resource
    private WebSocket webSocket;

    @Resource
    private IQuartzManager quartzManager;

    @Resource
    private IBusWellInfoSupportService busWellInfoService;

    @Override
    public List<Map<String, Object>> jobList(Page<Map<String, Object>> page, String keywords, String beginTime, String endTime, String jobStatus, String alarmType, String alarmContent, DataScope dataScope, Long userId) {
        alarmContent = converAlarmContent(alarmContent);
        List<Map<String, Object>> alarmJobList = this.baseMapper.jobList(page, keywords, beginTime, endTime, jobStatus, alarmType, alarmContent, dataScope, userId);
        return alarmJobList;
    }

    @Override
    public List<Map<String, Object>> jobListApp(Page<Map<String, Object>> page, String keywords, String beginTime, String endTime, String jobStatus, String alarmType, String alarmContent, Long deptId, Long userId, Long leaderId) {
        alarmContent = converAlarmContent(alarmContent);
        List<Map<String, Object>> alarmJobList = this.baseMapper.jobListApp(page, keywords, beginTime, endTime, jobStatus, alarmType, alarmContent, deptId, userId, leaderId);
        return alarmJobList;
    }

    @Override
    public List<Map<String, Object>> jobListDelayRe(Page<Map<String, Object>> page, String keywords, String beginTime, String endTime, String alarmType, String alarmContent, DataScope dataScope, Long userId) {
        alarmContent = converAlarmContent(alarmContent);
        List<Map<String, Object>> alarmJobList = this.baseMapper.jobListDelayRe(page, keywords, beginTime, endTime, alarmType, alarmContent, dataScope, userId);
        return alarmJobList;
    }

    @Override
    public List<Map<String, Object>> jobListDelayReApp(Page<Map<String, Object>> page, String keywords, String beginTime, String endTime, String alarmType, String alarmContent, Long deptId, Long userId, Long leaderId) {
        alarmContent = converAlarmContent(alarmContent);
        List<Map<String, Object>> alarmJobList = this.baseMapper.jobListDelayReApp(page, keywords, beginTime, endTime, alarmType, alarmContent, deptId, userId, leaderId);
        return alarmJobList;
    }

    @Override
    public List<Map<String, Object>> jobListDelayPro(Page<Map<String, Object>> page, String keywords, String beginTime, String endTime, String alarmType, String alarmContent, DataScope dataScope, Long userId) {
        alarmContent = converAlarmContent(alarmContent);
        List<Map<String, Object>> alarmJobList = this.baseMapper.jobListDelayPro(page, keywords, beginTime, endTime, alarmType, alarmContent, dataScope, userId);
        return alarmJobList;
    }

    @Override
    public List<Map<String, Object>> jobListDelayProApp(Page<Map<String, Object>> page, String keywords, String beginTime, String endTime, String alarmType, String alarmContent, Long deptId, Long userId, Long leaderId) {
        alarmContent = converAlarmContent(alarmContent);
        List<Map<String, Object>> alarmJobList = this.baseMapper.jobListDelayProApp(page, keywords, beginTime, endTime, alarmType, alarmContent, deptId, userId, leaderId);
        return alarmJobList;
    }

    @Override
    public List<Map<String, Object>> jobListSearch(Page<Map<String, Object>> page, JobListParam jobListParam, DataScope dataScope, Long userId) {
        jobListParam.setAlarmContent(converAlarmContent(jobListParam.getAlarmContent()));
        List<Map<String, Object>> alarmJobList = this.baseMapper.jobListSearch(page, jobListParam, dataScope, userId);
        return alarmJobList;
    }

    @Override
    public List<Map<String, Object>> jobListSearchApp(Page<Map<String, Object>> page, JobListParam jobListParam, Long deptId, Long userId, Long leaderId) {
        jobListParam.setAlarmContent(converAlarmContent(jobListParam.getAlarmContent()));
        List<Map<String, Object>> alarmJobList = this.baseMapper.jobListSearchApp(page, jobListParam.getKeywords(),
                jobListParam.getAlarmLevel(), jobListParam.getAlarmContent(), jobListParam.getJobStatus(), jobListParam.getBeginTime(),
                jobListParam.getEndTime(), jobListParam.getGetJobBeginTime(), jobListParam.getGetJobEndTime(), jobListParam.getShouldGetBeginTime(),
                jobListParam.getShouldGetEndTime(), jobListParam.getHandleJobBeginTime(), jobListParam.getHandleJobEndTime(), jobListParam.getShouldHandleBeginTime(),
                jobListParam.getShouldHandleEndTime(), deptId, userId, leaderId);
        return alarmJobList;
    }

    private String converAlarmContent(String alarmContent) {
        if (StrUtil.isEmpty(alarmContent)) {
            return alarmContent;
        } else {
            return EhcacheConstant.retBean().getAlarmContentName(Integer.valueOf(alarmContent));
        }
    }

    @Override
    public List<Map<String, Object>> jobInfo(Long id, DataScope dataScope, Long personId) {
        List<Map<String, Object>> jobList = this.baseMapper.jobInfo(id, dataScope, personId);
        jobList.forEach(job -> job.put("editable", job.get("jobBelongTo") != null && job.get("jobBelongTo").toString().equals(personId) ? 1 : 0));
        return jobList;
    }

    @Override
    public Map<String, Object> countByJobStatus(long deptId, int spanDays) {
        return this.baseMapper.countByJobStatus(deptId, spanDays);
    }

    @Override
    public Map<String, Object> countMyJob(long userId, long deptId, int spanDays) {
        return this.baseMapper.countMyJob(userId, deptId, spanDays);
    }

    @Override
    public boolean getJob(Long id, long personId) {

        Calendar now = Calendar.getInstance();
        Date getTime = now.getTime();
        if (isWeekend(now)) {
            now.add(Calendar.WEEK_OF_YEAR, 1);
            now.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
            now.set(Calendar.HOUR_OF_DAY, 8);
            now.set(Calendar.MINUTE, 0);
            now.set(Calendar.SECOND, 0);
        } else {
            now.add(Calendar.HOUR, 24);
            while (isWeekend(now)) {
                now.add(Calendar.HOUR, 24);
            }
        }
        Date shouldHandleTime = now.getTime();
        if (Boolean.getBoolean(useOverTime)) {
            System.out.println(shouldHandleTime);
            String jobName = "getJobDelay" + id;
            Map<String, Object> map = new HashMap<>();
            map.put("jobId", id);
            map.put("iAlarmJobService", this);
            map.put("iCommonUserService", iCommonUserService);
            map.put("iQuartzManager", quartzManager);
            map.put("webSocket", webSocket);
            quartzManager.addJob(jobName, DelayJob.class, shouldHandleTime, map);
        }

        return this.baseMapper.getJob(id, personId, getTime, shouldHandleTime);
    }

    private boolean isWeekend(Calendar cal) {
        if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean confirmJob(Long id, long personId, String firstState, String firstStatePhotos, String needHandle) {
        if ("1".equals(needHandle)) {
            return this.baseMapper.confirmJob(id, personId, firstState, firstStatePhotos, needHandle);
        } else {
            return this.baseMapper.confirmOverJobAndAlarm(id, personId, firstState, firstStatePhotos) && this.baseMapper.confirmOverAlarmRecords(id);
        }
    }

    @Override
    public boolean transferJob(Long id, long transferPerson, String flowRec) {
        return this.baseMapper.transferJob(id, transferPerson, flowRec);
    }

    @Override
    public boolean saveJob(Long id, String handleMessage, String handlePhotos) {
        return this.baseMapper.saveJob(id, handleMessage, handlePhotos);
    }

    @Override
    public boolean overJob(Long id, long personId, String handleMessage, String handlePhotos) {
        return this.baseMapper.overJob(id, personId, handleMessage, handlePhotos) && this.baseMapper.overJobAlarmRecrds(id);
    }

    @Override
    public boolean overAlarm(Long jobId) {
        return this.baseMapper.overAlarm(jobId);
//        return this.baseMapper.overJob(id, personId,handleMessage, handlePhotos);
    }

    @Override
    public boolean handleJob(Long id, long personId) {
        return this.baseMapper.handleJob(id, personId);
    }

    @Override
    public boolean checkJobStatus(String jobStatus) {
        if (StrUtil.isEmpty(jobStatus)) {
            return false;
        } else {
            return "1".equals(jobStatus) || "2".equals(jobStatus) || "3".equals(jobStatus);
        }
    }

    @Override
    public List<UserClientView> selectUserByWellCode(String wellCode) {
        return this.baseMapper.selectUserByWellCode(wellCode);
    }


    public List<SelectDto> selectRoles() {
        return this.baseMapper.selectRoles();
    }

    public List<Long> selectUseIds(List<Long> roleIds) {
        return this.baseMapper.selectUseIds(roleIds);
    }

    @Override
    public boolean checkPcRole(Set<String> roleTips) {
        List<String> roleList = new ArrayList<>(roleTips);
        Iterator<String> it = roleList.iterator();
        while (it.hasNext()) {
            String role = it.next();
            if (role.equals(sApp) || role.equals(sLeader) || role.equals(sMember)) {
                it.remove();
            }
        }
        return roleList.size() > 0;
    }

    @Override
    public Integer countByDataScope(DataScope dataScope, String alarmType, String jobStatus, String beginTime, String endTime) {
//        try {
//            Date startTime = timeFormat.parse(beginTime);
//            Date lastTime = timeFormat.parse(endTime);
        List<Map<String, Object>> res = this.baseMapper.countByDataScope(dataScope, alarmType, jobStatus, beginTime, endTime);
        return res.size();
//
//        } catch (ParseException ex) {
//            log.error("主题：日期格式转换出错，开始日期{}，结束日期{}，异常信息{}",beginTime,endTime,ex);
//        }
//        return null;
    }

    @Override
    public Integer countByResponse(String alarmType, String jobStatus, Long deptId, String beginTime, String endTime) {
        return this.baseMapper.countByResponse(alarmType, jobStatus, deptId, beginTime, endTime);
    }

    @Override
    public Integer countByUser(String alarmType, String jobStatus, Long userId, String beginTime, String endTime) {
        return this.baseMapper.countByUser(alarmType, jobStatus, userId, beginTime, endTime);
    }


    @Override
    public void updateSinkJob(String id, String msg, String wellCode) {
        List<UserClientView> userClientViewList = new ArrayList<>();
        List<SelectDto> selectDtoList = selectRoles();
        QueryWrapper<BusWellInfo> busWellInfoEntityWrapper = new QueryWrapper<>();
        busWellInfoEntityWrapper.eq("WELL_CODE", wellCode);
        BusWellInfo busWellInfo = busWellInfoService.selectOne(busWellInfoEntityWrapper);
        if (busWellInfo != null && ObjectUtil.isEmpty(busWellInfo.getDeptid())) {
            List<Long> roleids = new ArrayList<>();
            for (SelectDto selectDto : selectDtoList) {
                if (StrUtil.isNotEmpty(selectDto.getName())
                        && Arrays.asList(selectDto.getName().split(",")).contains(busWellInfo.getDeptid())) {
                    roleids.add(selectDto.getId());
                }
            }
            if (roleids.size() > 0) {
                List<Long> useIds = selectUseIds(roleids);
                for (Long useId : useIds) {
                    UserClientView userClientView = new UserClientView();
                    userClientView.setClientid(useId.toString());
                    userClientView.setId(useId.toString());
                    userClientViewList.add(userClientView);
                }
            }
        }

        if (!(StrUtil.isEmpty(id))) {
            AlarmJob alarmJob = this.baseMapper.selectById(Long.valueOf(id));
            if (alarmJob != null) {
                sendJob(id, alarmJob, userClientViewList);//推送工单至app和pc端
            }
        }
        if (StrUtil.isNotBlank(msg)) {
            sendAlarm(msg, userClientViewList);//推送告警至app和pc端
        }

    }


    public void sendAlarm(String msg, List<UserClientView> userClientViewList) {
        List<String> clientIds = new ArrayList<>();
        List<String> userIds = new ArrayList<>();
        for (UserClientView userClientView : userClientViewList) {
            if (StrUtil.isNotEmpty(userClientView.getClientid())) {
                clientIds.add(userClientView.getClientid());
            }
            if (StrUtil.isNotEmpty(userClientView.getId())) {
                userIds.add(userClientView.getId());
            }
        }
        if (clientIds.size() > 0) {
            IPushResult pushResult = PushList.pushToUser(clientIds, "告警提醒", msg);
            if ("ok".equals(pushResult.getResponse().get("result").toString())) {
                logger.info("告警消息app端推送成功:" + msg);
            } else {
                logger.info("告警消息app端推送失败:" + msg);
            }
        } else {
            logger.info("告警消息app端找不到责任人，未推送:" + msg);
        }
        // PC推送,推给信息办
        // List<User> userList = permissionService.getRoleUsersByTips("1178242562491285506",null,false);
        List<User> userList = EhcacheConstant.retBean().getUserByDeptId(Long.valueOf("1178242562491285506"));
        for (User user : userList) {
            userIds.add(user.getId().toString());
        }
        if (userIds.size() > 0) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("message", msg);
            map.put("type", "alarm");
            webSocket.sendListMessage(userIds, JSON.toJSONString(map));
        } else {
            logger.info("告警消息找不到责任人，pc端未推送:" + msg);
        }

    }

    public void sendJob(String id, AlarmJob alarmJob, List<UserClientView> userClientViewList) {

        Calendar now = Calendar.getInstance();
        if (isWeekend(now)) {
            now.add(Calendar.WEEK_OF_YEAR, 1);
            now.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
            now.set(Calendar.HOUR_OF_DAY, 10);//默认8点上班
            now.set(Calendar.MINUTE, 0);
            now.set(Calendar.SECOND, 0);
        } else {
            try {
                if (isTimeRange()) {
                    now.add(Calendar.HOUR_OF_DAY, 2);
                } else {
                    now.set(Calendar.HOUR_OF_DAY, 10);//默认8点上班
                    now.set(Calendar.MINUTE, 0);
                    now.set(Calendar.SECOND, 0);
                    if (!compareNoon()) {
                        now.add(Calendar.DAY_OF_MONTH, +1);

                    }
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }

        }
        Date shouldHandleTime = now.getTime();
        if (Boolean.getBoolean(useOverTime)) {
            System.out.println(shouldHandleTime);
            String jobName = "getJobDelay" + id;
            Map<String, Object> map = new HashMap<>();
            map.put("jobId", id);
            map.put("iAlarmJobService", this);
            map.put("iCommonUserService", iCommonUserService);
            map.put("iQuartzManager", quartzManager);
            map.put("webSocket", webSocket);
            map.put("userClientViewList", userClientViewList);
            quartzManager.addJob(jobName, HandleAlarmJob.class, shouldHandleTime, map);
            alarmJob.setShouldGetTime(shouldHandleTime);
        }
        this.baseMapper.updateById(alarmJob);
    }

    private boolean isTimeRange() throws ParseException {//接单时间默认朝八晚八
        SimpleDateFormat df = new SimpleDateFormat("HH:mm");
        Date now = df.parse(df.format(new Date()));
        Date begin = df.parse("8:00");
        Date end = df.parse("20:00");
        Calendar nowTime = Calendar.getInstance();
        nowTime.setTime(now);
        Calendar beginTime = Calendar.getInstance();
        beginTime.setTime(begin);
        Calendar endTime = Calendar.getInstance();
        endTime.setTime(end);
        if (nowTime.before(endTime) && nowTime.after(beginTime)) {
            return true;
        } else {
            return false;
        }
    }

    public boolean compareNoon() {
        Date date = new Date();
        SimpleDateFormat df = new SimpleDateFormat("HH");
        String str = df.format(date);
        int a = Integer.parseInt(str);
        if (a >= 0 && a <= 12) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public String selectClientIdByUser(Long userId) {
        return this.baseMapper.selectClientIdByUser(userId);
    }
}
