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.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.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.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 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.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.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 CareConfigService careConfigService;

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

    }

    private void syncWaitAndFinQueue() {
        List<WaitPersonInfo> waitPersonInfos = new ArrayList<>();
        List<FinPersonInfo> finPersonInfos = new ArrayList<>();
        cacheService.select(redisDb);//
        while (true) {
            WaitPersonInfo waitPersonInfo = cacheService.lpop(RedisKey.KEY_WAITNUM_LIST_CACHE, WaitPersonInfo.class);
            if (ObjectUtils.isEmpty(waitPersonInfo)) {
                break;
            } else {
                waitPersonInfos.add(waitPersonInfo);
            }
        }
        while (true) {
            FinPersonInfo finPersonInfo = cacheService.lpop(RedisKey.KEY_FIN_LIST_CACHE, FinPersonInfo.class);
            if (ObjectUtils.isEmpty(finPersonInfo)) {
                break;
            } else {
                finPersonInfos.add(finPersonInfo);
            }
        }
        cacheService.select(database);//
        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);
                    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);
                }
            }
        }
    }

    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);

    }


}
