package com.mortals.xhx.daemon.task;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.service.ICacheService;
import com.mortals.framework.service.ITask;
import com.mortals.framework.service.ITaskExcuteService;
import com.mortals.framework.util.DataUtil;
import com.mortals.framework.util.DateUtils;
import com.mortals.xhx.base.system.user.model.UserEntity;
import com.mortals.xhx.base.system.user.service.UserService;
import com.mortals.xhx.busiz.rsp.register.AppointmentDataInfo;
import com.mortals.xhx.busiz.rsp.register.AppointmentDataItem;
import com.mortals.xhx.busiz.rsp.wait.CpPersonInfo;
import com.mortals.xhx.busiz.rsp.wait.EndPersonInfo;
import com.mortals.xhx.busiz.rsp.wait.FinPersonInfo;
import com.mortals.xhx.busiz.rsp.wait.WaitPersonInfo;
import com.mortals.xhx.common.code.ProcessStatusEnum;
import com.mortals.xhx.common.code.UserType;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.key.RedisKey;
import com.mortals.xhx.module.alarm.model.AlarmRecordsEntity;
import com.mortals.xhx.module.alarm.service.AlarmRecordsService;
import com.mortals.xhx.module.appointment.model.AppointmentPersonEntity;
import com.mortals.xhx.module.appointment.model.AppointmentPersonQuery;
import com.mortals.xhx.module.appointment.service.AppointmentPersonService;
import com.mortals.xhx.module.care.model.*;
import com.mortals.xhx.module.care.service.CareConfigService;
import com.mortals.xhx.module.care.service.CareCpRecordsService;
import com.mortals.xhx.module.care.service.CareDoworkRecordsService;
import com.mortals.xhx.module.care.service.CareRecordsService;
import com.mortals.xhx.module.hik.person.model.rsp.person.PersonInfo;
import com.mortals.xhx.module.notice.model.NoticeEntity;
import com.mortals.xhx.module.notice.service.NoticeService;
import com.mortals.xhx.module.person.model.PersonEntity;
import com.mortals.xhx.module.person.service.PersonService;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.statement.ExplainStatement;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.kafka.common.protocol.types.Field;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 同步取号等待人群与完成人群结果。
 * 通过redis list 获取
 */
@Slf4j
@Service("SyncAppointWaitAndFinTask")
public class SyncAppointWaitAndFinTaskImpl implements ITaskExcuteService {

    @Autowired
    private ICacheService cacheService;

    @Value("${php.host:''}")
    private String host;

    @Value("${php.redisDb:''}")
    private Integer redisDb;

    @Value("${spring.redis.database:''}")
    private Integer database;

    @Autowired
    private CareRecordsService careRecordsService;

    @Autowired
    private CareDoworkRecordsService careDoworkRecordsService;

    @Autowired
    private CareConfigService careConfigService;
    @Autowired
    private AlarmRecordsService alarmRecordsService;
    @Autowired
    private CareCpRecordsService careCpRecordsService;

    @Override
    public void excuteTask(ITask task) throws AppException {
        log.debug("同步今天等待用户任务");
        syncWaitAndFinQueue();
        log.debug("同步今天等待用户完成任务");
        log.info("关怀用户任务");
        updateWaitQueueTime();
        log.info("关怀服务完成任务");
        log.debug("清理超期等待业务");
        clearWaitQueueTime();
        //todo 办理完成同步
        log.info("同步办理完成业务");

        //todo 差评同步
        log.info("差评业务");

    }

    private void syncWaitAndFinQueue() {
        RedisTemplate<String, String> redisTemplate = cacheService.selectDbRedisTemplate(redisDb);
        //  cacheService.select(redisDb);//
        new Thread(() -> {
            List<WaitPersonInfo> waitPersonInfos = new ArrayList<>();
            List<FinPersonInfo> finPersonInfos = new ArrayList<>();
            List<EndPersonInfo> endPersonInfos = new ArrayList<>();
            while (true) {
                String value = redisTemplate.opsForList().leftPop(RedisKey.KEY_WAITNUM_LIST_CACHE, 10, TimeUnit.SECONDS);
                WaitPersonInfo waitPersonInfo = JSON.parseObject(value, WaitPersonInfo.class);
                //  WaitPersonInfo waitPersonInfo = cacheService.blpop(RedisKey.KEY_WAITNUM_LIST_CACHE,10, WaitPersonInfo.class);
                if (ObjectUtils.isEmpty(waitPersonInfo)) {
                    break;
                } else {
                    waitPersonInfos.add(waitPersonInfo);
                }
            }

            while (true) {
                String value = redisTemplate.opsForList().leftPop(RedisKey.KEY_FIN_LIST_CACHE, 10, TimeUnit.SECONDS);
                FinPersonInfo finPersonInfo = JSON.parseObject(value, FinPersonInfo.class);
                //  FinPersonInfo finPersonInfo = cacheService.blpop(RedisKey.KEY_FIN_LIST_CACHE,10, FinPersonInfo.class);
                if (ObjectUtils.isEmpty(finPersonInfo)) {
                    break;
                } else {
                    finPersonInfos.add(finPersonInfo);
                }
            }

            while (true) {
                String value = redisTemplate.opsForList().leftPop(RedisKey.KEY_FIN_DOWORK_LIST_CACHE, 10, TimeUnit.SECONDS);
                EndPersonInfo endPersonInfo = JSON.parseObject(value, EndPersonInfo.class);
                //  FinPersonInfo finPersonInfo = cacheService.blpop(RedisKey.KEY_FIN_LIST_CACHE,10, FinPersonInfo.class);
                if (ObjectUtils.isEmpty(endPersonInfo)) {
                    break;
                } else {
                    endPersonInfos.add(endPersonInfo);
                }
            }


            if (!ObjectUtils.isEmpty(waitPersonInfos)) {
                // log.info("waitPersonInfos:{}", JSON.toJSONString(waitPersonInfos));
                List<CareRecordsEntity> recordsEntityList = waitPersonInfos.stream().map(item -> {
                    CareRecordsEntity careRecordsEntity = new CareRecordsEntity();
                    careRecordsEntity.initAttrValue();
                    careRecordsEntity.setName(item.getIdcardName());
                    careRecordsEntity.setContact(item.getPhone());
                    careRecordsEntity.setIdCard(item.getIdcardIDCardNo());
                    careRecordsEntity.setBussinessId(item.getBusinessId());
                    careRecordsEntity.setBussinessName(item.getBusinessName());
                    careRecordsEntity.setService(item.getBusinessName());
                    careRecordsEntity.setQueueNo(item.getFlowNum());
                    careRecordsEntity.setMonitorTime(new Date());
                    careRecordsEntity.setTakeTime(item.getTakeTime() == null ? new Date() : item.getTakeTime());
                    careRecordsEntity.setPersonId(DataUtil.converStr2Long(item.getPeopleId(), 0));
                    careRecordsEntity.setWaitId(item.getWaitId());
                    careRecordsEntity.setProcessStatus(ProcessStatusEnum.排队中.getValue());
                    careRecordsEntity.setCreateTime(new Date());
                    careRecordsEntity.setCreateUserName("system");
                    careRecordsEntity.setCreateUserId(1L);
                    return careRecordsEntity;
                }).collect(Collectors.toList());

                if (!ObjectUtils.isEmpty(recordsEntityList)) {
                    log.info("保存关怀记录数量，size:{}", recordsEntityList.size());
                    careRecordsService.save(recordsEntityList);
                }
            }

            if (!ObjectUtils.isEmpty(finPersonInfos)) {
                log.info("finPersonInfos:{}", JSON.toJSONString(finPersonInfos));
                List<Long> waitIdList = finPersonInfos.stream().map(item -> item.getWaitId()).collect(Collectors.toList());
                Map<Long, FinPersonInfo> waitMap = finPersonInfos.stream().collect(Collectors.toMap(x -> x.getWaitId(), y -> y, (o, n) -> n));

                CareRecordsQuery careRecordsQuery = new CareRecordsQuery();
                careRecordsQuery.setWaitIdList(waitIdList);
                List<CareRecordsEntity> careRecordsEntities = careRecordsService.find(careRecordsQuery);
                if (!ObjectUtils.isEmpty(careRecordsEntities)) {
                    careRecordsEntities.forEach(item -> {
                        FinPersonInfo finPersonInfo = waitMap.get(item.getWaitId());
                        item.setProcessStatus(ProcessStatusEnum.接件结束.getValue());
                        item.setCallTime(finPersonInfo.getCalltime());
                        Long diff = DateUtil.between(item.getTakeTime(), finPersonInfo.getCalltime(), DateUnit.MINUTE);
                        if (!ObjectUtils.isEmpty(finPersonInfo.getAvgWaitTime())) {
                            int avgWait = finPersonInfo.getAvgWaitTime() / 60;
                            if (avgWait > 0
                                    && diff > avgWait) {
                                //todo 构造发送消息。
                                AlarmRecordsEntity recordsEntity = new AlarmRecordsEntity();
                                recordsEntity.initAttrValue();
                                String alarmContent = String.format("排队编号:%s:,%s业务叫号等待时间为%d分钟，超过了平均等待时长%d分钟!", item.getQueueNo(), item.getBussinessName(),diff - avgWait);
                                recordsEntity.setAlarmContent(alarmContent);
                                recordsEntity.setAlarmTime(new Date());
                                recordsEntity.setCreateTime(new Date());
                                recordsEntity.setCreateUserId(1L);
                                alarmRecordsService.save(recordsEntity);
                            }
                        }
                        //判断是否大于平均等待时间，如果大于 则预警消息
                        item.setWaitTime(diff.intValue());
                        item.setUpdateTime(new Date());
                        item.setUpdateUserId(1L);
                        item.setUpdateUserName("system");
                    });
                    if (!ObjectUtils.isEmpty(careRecordsEntities)) {
                        log.info("更新关怀记录数量，size:{}", careRecordsEntities.size());
                        careRecordsService.update(careRecordsEntities);
                    }
                }
            }

            if (!ObjectUtils.isEmpty(endPersonInfos)) {
                log.info("endPersonInfos:{}", JSON.toJSONString(endPersonInfos));
                List<Long> endIdList = endPersonInfos.stream().map(item -> item.getEndId()).collect(Collectors.toList());
                Map<Long, EndPersonInfo> endMap = endPersonInfos.stream().collect(Collectors.toMap(x -> x.getEndId(), y -> y, (o, n) -> n));

                CareRecordsQuery careRecordsQuery = new CareRecordsQuery();
                careRecordsQuery.setWaitIdList(endIdList);
                List<CareRecordsEntity> careRecordsEntities = careRecordsService.find(careRecordsQuery);
                if (!ObjectUtils.isEmpty(careRecordsEntities)) {
                    careRecordsEntities.forEach(item -> {
                        EndPersonInfo endPersonInfo = endMap.get(item.getWaitId());
                        item.setProcessStatus(ProcessStatusEnum.办理结束.getValue());
                        item.setEndTime(endPersonInfo.getEndtime());
                        Long diff = DateUtil.between(item.getCallTime(), endPersonInfo.getEndtime(), DateUnit.MINUTE);

                        if (!ObjectUtils.isEmpty(endPersonInfo.getAvgHandleTime())) {
                            int avgWait = endPersonInfo.getAvgHandleTime() / 60;
                            if (avgWait > 0
                                    && diff > avgWait) {
                                //todo 构造发送消息。
                                AlarmRecordsEntity recordsEntity = new AlarmRecordsEntity();
                                recordsEntity.initAttrValue();
                                String alarmContent = String.format("编号:%s:,%s业务办理时间为%d分钟，超过了平均办理时长%d分钟!",  item.getBussinessName(),diff - avgWait);
                                recordsEntity.setAlarmContent(alarmContent);
                                recordsEntity.setAlarmTime(new Date());
                                recordsEntity.setCreateTime(new Date());
                                recordsEntity.setCreateUserId(1L);
                                alarmRecordsService.save(recordsEntity);
                            }
                        }

                        item.setEndDureTime(diff.intValue());
                        item.setUpdateTime(new Date());
                        item.setUpdateUserId(1L);
                        item.setUpdateUserName("system");
                    });
                    if (!ObjectUtils.isEmpty(careRecordsEntities)) {
                        log.info("更新办理结束记录数量，size:{}", careRecordsEntities.size());
                        careRecordsService.update(careRecordsEntities);
                    }
                }
            }
        }).start();


        //好差评
        new Thread(() -> {
            List<CpPersonInfo> cpPersonInfos = new ArrayList<>();
            while (true) {
                String value = redisTemplate.opsForList().leftPop(RedisKey.KEY_CP_LIST_CACHE, 10, TimeUnit.SECONDS);
                CpPersonInfo cpPersonInfo = JSON.parseObject(value, CpPersonInfo.class);
                //  FinPersonInfo finPersonInfo = cacheService.blpop(RedisKey.KEY_FIN_LIST_CACHE,10, FinPersonInfo.class);
                if (ObjectUtils.isEmpty(cpPersonInfo)) {
                    break;
                } else {
                    cpPersonInfos.add(cpPersonInfo);
                }
            }
            // cacheService.select(database);//
            if (!ObjectUtils.isEmpty(cpPersonInfos)) {
                log.info("cpPersonInfos:{}", JSON.toJSONString(cpPersonInfos));
                for (CpPersonInfo cpPersonInfo : cpPersonInfos) {

                    CareCpRecordsEntity careCpRecordsEntity = new CareCpRecordsEntity();
                    careCpRecordsEntity.initAttrValue();
                    careCpRecordsEntity.setSiteId(cpPersonInfo.getSiteId());
                    careCpRecordsEntity.setPersonId(cpPersonInfo.getPeopleId());
                    careCpRecordsEntity.setPjId(cpPersonInfo.getPjId());
                    careCpRecordsEntity.setWindowName(cpPersonInfo.getWindowName());
                    careCpRecordsEntity.setSection(cpPersonInfo.getSection());
                    careCpRecordsEntity.setFlounum(cpPersonInfo.getFlounum());
                    careCpRecordsEntity.setAssessment(cpPersonInfo.getOptionId());
                    careCpRecordsEntity.setType(cpPersonInfo.getType());
                    careCpRecordsEntity.setContent(cpPersonInfo.getContent());
                    careCpRecordsEntity.setSource(cpPersonInfo.getSource());
                    careCpRecordsEntity.setPjTime(cpPersonInfo.getCpTime());
                    careCpRecordsEntity.setName(cpPersonInfo.getWorkmanName());
                    careCpRecordsEntity.setCreateTime(new Date());
                    careCpRecordsEntity.setCreateUserId(1L);
                    careCpRecordsService.save(careCpRecordsEntity);

                    //发送差评消息
                    AlarmRecordsEntity recordsEntity = new AlarmRecordsEntity();
                    recordsEntity.initAttrValue();
                    String alarmContent = String.format(
                            "客户对窗口:%s:,工作人员%s 发起评价:%s，评价内容:%s!",
                            careCpRecordsEntity.getWindowName(),cpPersonInfo.getWorkmanName(),cpPersonInfo.getOptionId(),cpPersonInfo.getContent());
                    recordsEntity.setAlarmContent(alarmContent);
                    recordsEntity.setAlarmTime(new Date());
                    recordsEntity.setCreateTime(new Date());
                    recordsEntity.setCreateUserId(1L);
                    alarmRecordsService.save(recordsEntity);
                }
            }
        }).start();


    }


    private void updateWaitQueueTime() {
        CareConfigEntity careConfigEntity = careConfigService.selectOne(new CareConfigQuery());
        List<CareRecordsEntity> careRecordsEntities = careRecordsService.find(new CareRecordsQuery().processStatus(ProcessStatusEnum.排队中.getValue()));
        log.info("排队数量:{}", careRecordsEntities.size());
        if (!ObjectUtils.isEmpty(careRecordsEntities)) {
            //更新等待时长
            List<CareRecordsEntity> recordsEntities = careRecordsEntities.stream().map(item -> {
                Long diff = DateUtil.between(item.getTakeTime(), new Date(), DateUnit.MINUTE);
                item.setWaitTime(diff.intValue());
                item.setUpdateTime(new Date());
                item.setUpdateUserId(1L);
                item.setUpdateUserName("system");
                return item;
            }).collect(Collectors.toList());
            careRecordsService.update(recordsEntities);

            //查询关怀配置，发送管理员通知消息
            if (!ObjectUtils.isEmpty(careConfigEntity)) {
                if (checkCareServiceUsed(careConfigEntity)) return;
                //校验当天日期是否启用
                if (checkCareServiceDay(careConfigEntity)) return;
                //校验当天服务最大人数
                if (checkCareServiceMaxNum(careConfigEntity)) return;
                //校验当天服务时间段
                if (checkServiceTimeDurion(careConfigEntity)) return;

                Long serviceThreshold = careConfigEntity.getServiceThreshold();
                String msgRecipients = careConfigEntity.getMsgRecipients();

                List<CareRecordsEntity> waitCareList = recordsEntities.stream()
                        .filter(f -> f.getCareCount() == 0)
                        .filter(f -> f.getWaitTime() > serviceThreshold.intValue())
                        .collect(Collectors.toList());
                log.info("待关怀的人数:{}", waitCareList.size());
                if (!ObjectUtils.isEmpty(waitCareList)) {
                    waitCareList.forEach(waitCare -> {
                        //发送消息给管理员
                        if (StrUtil.contains(msgRecipients, "管理员")) {
                            careRecordsService.notice(waitCare, null);
                        }
                        //发送短信消息给办事群众
                        if (StrUtil.contains(msgRecipients, "办事群众")) {
                            careRecordsService.toCare(waitCare, null);
                        }
                    });
                }
            }

        }
    }


    private void clearWaitQueueTime() {
        //查询所有昨天以前的等待队列，并手动结束排队
        CareRecordsQuery careRecordsQuery = new CareRecordsQuery();
        careRecordsQuery.setProcessStatus(ProcessStatusEnum.排队中.getValue());
        careRecordsQuery.setTakeTimeEnd(DateUtil.yesterday().toStringDefaultTimeZone());
        List<CareRecordsEntity> careRecordsEntities = careRecordsService.find(careRecordsQuery);
        //手动结束
        if (!ObjectUtils.isEmpty(careRecordsEntities)) {
            List<CareRecordsEntity> recordsEntities = careRecordsEntities.stream().map(item -> {
                Long diff = DateUtil.between(item.getTakeTime(), new Date(), DateUnit.MINUTE);
                item.setWaitTime(diff.intValue());
                item.setProcessStatus(ProcessStatusEnum.接件结束.getValue());
                item.setAssessment("排队等待时间超过一天，系统自动结束！");
                item.setUpdateTime(new Date());
                item.setUpdateUserId(1L);
                item.setUpdateUserName("system");
                return item;
            }).collect(Collectors.toList());
            careRecordsService.update(recordsEntities);
        }
    }

    private boolean checkCareServiceUsed(CareConfigEntity careConfigEntity) {
        Integer used = careConfigEntity.getUsed();
        if (used == YesNoEnum.NO.getValue()) {
            log.info("关怀服务未启用！");
            return true;
        }
        return false;
    }

    private boolean checkCareServiceDay(CareConfigEntity careConfigEntity) {
        switch (DateTime.now().dayOfWeekEnum().getValue()) {
            case 1:
                if (careConfigEntity.getMonday() == 1) return false;
            case 2:
                if (careConfigEntity.getThursday() == 1) return false;
            case 3:
                if (careConfigEntity.getWednesday() == 1) return false;
            case 4:
                if (careConfigEntity.getThursday() == 1) return false;
            case 5:
                if (careConfigEntity.getFriday() == 1) return false;
            case 6:
                if (careConfigEntity.getSaturday() == 1) return false;
            case 7:
                if (careConfigEntity.getSunday() == 1) return false;
            default:
                return true;
        }
    }


    private boolean checkCareServiceMaxNum(CareConfigEntity careConfigEntity) {
        Integer maxServicePersonNum = careConfigEntity.getMaxServicePersonNum();
        CareRecordsQuery careRecordsQuery = new CareRecordsQuery();
        careRecordsQuery.setCareCountStart(1);
        careRecordsQuery.setCreateTimeStart(DateUtils.getCurrStrDate());
        careRecordsQuery.setCreateTimeEnd(DateUtils.getCurrStrDate());
        int dayServiceNum = careRecordsService.count(careRecordsQuery, null);
        if (dayServiceNum > maxServicePersonNum) {
            log.info("关怀服务人数超过最大数量！当天关怀人数：{}，配置最大关怀人数：{}", dayServiceNum, maxServicePersonNum);
            return true;
        }
        return false;
    }


    private boolean checkServiceTimeDurion(CareConfigEntity careConfigEntity) {
        List<CareConfigTimesEntity> careConfigTimesList = careConfigEntity.getCareConfigTimesList();
        if (ObjectUtils.isEmpty(careConfigTimesList)) {
            Date date = new Date();
            boolean isIn = careConfigTimesList.stream()
                    .anyMatch((tp) -> (tp.getServiceTimeStart().equals(date) || tp.getServiceTimeStart().before(date))
                            && (tp.getServiceTimeEnd().equals(date) || tp.getServiceTimeEnd().after(date)));
            if (!isIn) {
                log.info("当前时间不在服务时间内！");
                return true;
            }
        }
        return false;
    }

    @Override
    public void stopTask(ITask task) throws AppException {

    }


    public static void main(String[] args) {


        Date date = new Date();  // 待判断的时间对象
        List<CareConfigTimesEntity> timePeriodList = new ArrayList<>();  // 时间段列表
        CareConfigTimesEntity careConfigTimesEntity = new CareConfigTimesEntity();
        careConfigTimesEntity.setServiceTimeStart(DateUtil.parse("2023-04-19 09:00:00"));
        careConfigTimesEntity.setServiceTimeEnd(DateUtil.parse("2023-04-19 10:00:00"));
        timePeriodList.add(careConfigTimesEntity);

        careConfigTimesEntity = new CareConfigTimesEntity();

        careConfigTimesEntity.setServiceTimeStart(DateUtil.parse("2023-04-19 10:10:00"));
        careConfigTimesEntity.setServiceTimeEnd(DateUtil.parse("2023-04-19 11:00:00"));
        timePeriodList.add(careConfigTimesEntity);


        boolean isIn = timePeriodList.stream()
                .anyMatch((tp) -> (tp.getServiceTimeStart().equals(date) || tp.getServiceTimeStart().before(date))
                        && (tp.getServiceTimeEnd().equals(date) || tp.getServiceTimeEnd().after(date)));
        System.out.println(isIn);

    }


}
