package cn.hnthyy.thmz.service.impl.thmz;

import cn.hnthyy.thmz.Utils.CloneUtil;
import cn.hnthyy.thmz.Utils.DateUtil;
import cn.hnthyy.thmz.common.Constants;
import cn.hnthyy.thmz.entity.MzException;
import cn.hnthyy.thmz.entity.his.mz.Employee;
import cn.hnthyy.thmz.entity.his.mz.MzPatientMi;
import cn.hnthyy.thmz.entity.his.mz.MzYjReq;
import cn.hnthyy.thmz.entity.his.zd.ZdUnitCode;
import cn.hnthyy.thmz.entity.thmz.ScheduleOfMedical;
import cn.hnthyy.thmz.entity.thmz.ScheduleOfMedicalApply;
import cn.hnthyy.thmz.entity.thmz.User;
import cn.hnthyy.thmz.enums.ScheduleOfMedicalEnum;
import cn.hnthyy.thmz.enums.YesNoEnum;
import cn.hnthyy.thmz.mapper.his.mz.EmployeeMapper;
import cn.hnthyy.thmz.mapper.thmz.ScheduleOfMedicalApplyMapper;
import cn.hnthyy.thmz.mapper.thmz.ScheduleOfMedicalMapper;
import cn.hnthyy.thmz.mapper.thmz.UserMapper;
import cn.hnthyy.thmz.service.his.mz.MzPatientMiService;
import cn.hnthyy.thmz.service.his.mz.MzYjReqService;
import cn.hnthyy.thmz.service.his.zd.ZdUnitCodeService;
import cn.hnthyy.thmz.service.thmz.HaiCiAdapterService;
import cn.hnthyy.thmz.service.thmz.MessageService;
import cn.hnthyy.thmz.service.thmz.ScheduleOfMedicalService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@Service
public class ScheduleOfMedicalServiceImpl implements ScheduleOfMedicalService {
    @SuppressWarnings("all")
    @Autowired
    private ScheduleOfMedicalMapper scheduleOfMedicalMapper;
    @SuppressWarnings("all")
    @Autowired
    private ScheduleOfMedicalApplyMapper scheduleOfMedicalApplyMapper;
    @SuppressWarnings("all")
    @Autowired
    private EmployeeMapper employeeMapper;

    @SuppressWarnings("all")
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MessageService messageService;
    @Autowired
    private ZdUnitCodeService zdUnitCodeService;
    @Autowired
    private MzYjReqService mzYjReqService;
    @Autowired
    private MzPatientMiService mzPatientMiService;
    @Autowired
    private HaiCiAdapterService haiCiAdapterService;
    //医技预约审核驳回回调地址
    @Value("${callBackYJYYUrl}")
    private String callBackYJYYUrl;
    @Override
    @Transactional(value = "thmzTransactionManager", propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public int saveScheduleOfMedical(ScheduleOfMedical scheduleOfMedical,Long userId) throws MzException {
        scheduleOfMedical.setUpdateDate(new Date());
        scheduleOfMedical.setUpdateId(userId);
        if(scheduleOfMedical.getId()==null){
            scheduleOfMedical.setCreateDate(scheduleOfMedical.getUpdateDate());
            scheduleOfMedical.setCreateId(userId);
            scheduleOfMedical.setStatus(YesNoEnum.NO.code);

            Long intervalMinutes =DateUtil.getIntervalMinutes(scheduleOfMedical.getBeginTime(),scheduleOfMedical.getEndTime());
            if(intervalMinutes%scheduleOfMedical.getTotalNum()!=0){
                throw new MzException("当前时间间隔无法被可预约号数整除，请调整预约时间范围或者预约号数！");
            }
            List<ScheduleOfMedical> scheduleOfMedicalList = new ArrayList<>();
            //每个时间段的间隔时间 分
            Long everMinutes = intervalMinutes/scheduleOfMedical.getTotalNum();
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
            Calendar calendar = Calendar.getInstance();
            ScheduleOfMedical prevScheduleOfMedical =scheduleOfMedical;
            for (int i=0;i<scheduleOfMedical.getTotalNum();i++){
                ScheduleOfMedical cloneScheduleOfMedical = CloneUtil.clone(prevScheduleOfMedical);
                String [] arr =null;
                if(i==0){
                    arr = prevScheduleOfMedical.getBeginTime().split(":");
                }else {
                    cloneScheduleOfMedical.setBeginTime(prevScheduleOfMedical.getEndTime());
                    arr = prevScheduleOfMedical.getEndTime().split(":");
                }
                calendar.set(Calendar.HOUR_OF_DAY, Integer.valueOf(arr[0]));
                calendar.set(Calendar.MINUTE, Integer.valueOf(arr[1]));
                calendar.add(Calendar.MINUTE, everMinutes.intValue());
                cloneScheduleOfMedical.setEndTime(sdf.format(calendar.getTime()));
                scheduleOfMedicalList.add(cloneScheduleOfMedical);
                prevScheduleOfMedical =cloneScheduleOfMedical;
            }
            return  scheduleOfMedicalMapper.batchInsertScheduleOfMedical(scheduleOfMedicalList);
        }
        return scheduleOfMedicalMapper.updateScheduleOfMedical(scheduleOfMedical);
    }

    @Override
    public List<ScheduleOfMedical> queryByCommonParams(ScheduleOfMedical scheduleOfMedical) {
        return scheduleOfMedicalMapper.selectByCommonParams(scheduleOfMedical);
    }

    @Override
    public int modifyScheduleOfMedical(ScheduleOfMedical scheduleOfMedical,Long userId) {
        scheduleOfMedical.setUpdateDate(new Date());
        scheduleOfMedical.setUpdateId(userId);
        return scheduleOfMedicalMapper.updateScheduleOfMedical(scheduleOfMedical);
    }

    @Override
    public int removeScheduleOfMedical(Long id) {
        return scheduleOfMedicalMapper.deleteScheduleOfMedical(id);
    }

    @Override
    public List<ScheduleOfMedical> queryScheduleOfMedicalWithPage(ScheduleOfMedical scheduleOfMedical) {
        return scheduleOfMedicalMapper.selectScheduleOfMedicalWithPage(scheduleOfMedical);
    }

    @Override
    public Integer queryCountScheduleOfMedical(ScheduleOfMedical scheduleOfMedical) {
        return scheduleOfMedicalMapper.selectCountScheduleOfMedical(scheduleOfMedical);
    }

    @Override
    public ScheduleOfMedical queryScheduleOfMedicalById(Long id) {
        return scheduleOfMedicalMapper.selectScheduleOfMedicalById(id);
    }

    @Override
    @Transactional(value = "thmzTransactionManager", propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public int applyScheduleOfMedical(ScheduleOfMedicalApply scheduleOfMedicalApply, User user){
        ScheduleOfMedical scheduleOfMedical = new ScheduleOfMedical();
        scheduleOfMedical.setId(scheduleOfMedicalApply.getScheduleId());
        scheduleOfMedical.setUpdateDate(new Date());
        scheduleOfMedical.setUpdateId(user.getId());
        //先执行更新时间和操作人操作，历史数据库锁实现锁定资源
        scheduleOfMedicalMapper.updateScheduleOfMedical(scheduleOfMedical);
        ScheduleOfMedical dbScheduleOfMedical=scheduleOfMedicalMapper.selectScheduleOfMedicalById(scheduleOfMedicalApply.getScheduleId());
        if(!ScheduleOfMedicalEnum.FREE.code.equals(dbScheduleOfMedical.getStatus())){
        //    throw new MzException("该医技排班已经被预约，无法重复预约！");
            throw new RuntimeException("该医技排班已经被预约，无法重复预约！");
        }
        Employee employee= employeeMapper.selectByUserCode(user.getUserIdCode());
        scheduleOfMedical.setStatus(ScheduleOfMedicalEnum.HOLDING.code);
        scheduleOfMedicalMapper.updateScheduleOfMedical(scheduleOfMedical);
        //ScheduleOfMedicalApply scheduleOfMedicalApply = new ScheduleOfMedicalApply();
       // scheduleOfMedicalApply.setScheduleId(scheduleOfMedicalApply.getScheduleId());
        scheduleOfMedicalApply.setCreateId(user.getId());
        scheduleOfMedicalApply.setCreateDeptNo(employee==null?null:employee.getDeptCode());
        scheduleOfMedicalApply.setCreateTime(scheduleOfMedical.getUpdateDate());
        int num= scheduleOfMedicalApplyMapper.insertScheduleOfMedicalApply(scheduleOfMedicalApply);
        //发送预约提示消息
        User createUser=userMapper.selectUserById(dbScheduleOfMedical.getCreateId());
        if(createUser!=null && StringUtils.isNotBlank(createUser.getUserCode())){
            ZdUnitCode zdUnitCode= zdUnitCodeService.queryByCode(dbScheduleOfMedical.getDepNo());
            String message= "您创建的科室【"+zdUnitCode.getName()+"】,日期【"+dbScheduleOfMedical.getRecordDate()+"】,开始时间【"+dbScheduleOfMedical.getBeginTime()+"】,结束时间【"+dbScheduleOfMedical.getEndTime()+"】对应的医技排班已经被";
            if(employee!=null && StringUtils.isNotBlank(employee.getDeptCode())){
                zdUnitCode= zdUnitCodeService.queryByCode(employee.getDeptCode());
                message+="【"+zdUnitCode.getName()+"】【"+user.getUserName()+"】预约,请及时处理！";
            }
            messageService.sendWxMessage(createUser.getUserCode(),message);
        }
        return num;
    }

    @Override
    @Transactional(value = "thmzTransactionManager",propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public int cancelApplyScheduleOfMedical(Long scheduleId, User user) throws Exception {
        ScheduleOfMedical scheduleOfMedical = new ScheduleOfMedical();
        scheduleOfMedical.setId(scheduleId);
        scheduleOfMedical.setUpdateDate(new Date());
        scheduleOfMedical.setUpdateId(user.getId());
        //先执行更新时间和操作人操作，历史数据库锁实现锁定资源
        scheduleOfMedicalMapper.updateScheduleOfMedical(scheduleOfMedical);
        ScheduleOfMedical dbScheduleOfMedical=scheduleOfMedicalMapper.selectScheduleOfMedicalById(scheduleId);
        if(!ScheduleOfMedicalEnum.HOLDING.code.equals(dbScheduleOfMedical.getStatus())){
            throw new MzException("该医技排班非占用状态，无法取消预约！");
        }
        scheduleOfMedical.setStatus(ScheduleOfMedicalEnum.FREE.code);
        scheduleOfMedicalMapper.updateScheduleOfMedical(scheduleOfMedical);
        ScheduleOfMedicalApply  scheduleOfMedicalApply=scheduleOfMedicalApplyMapper.selectByScheduleId(scheduleId);
        int num =0;
        if(scheduleOfMedicalApply!=null){
            num= scheduleOfMedicalApplyMapper.deleteScheduleOfMedicalApply(scheduleOfMedicalApply.getId());
        }
        //发送取消预约提示消息
        User createUser=userMapper.selectUserById(dbScheduleOfMedical.getCreateId());
        if(createUser!=null && StringUtils.isNotBlank(createUser.getUserCode())){
            ZdUnitCode zdUnitCode= zdUnitCodeService.queryByCode(dbScheduleOfMedical.getDepNo());
            String message= "您创建的科室【"+zdUnitCode.getName()+"】,日期【"+dbScheduleOfMedical.getRecordDate()+"】,开始时间【"+dbScheduleOfMedical.getBeginTime()+"】,结束时间【"+dbScheduleOfMedical.getEndTime()+"】对应的医技排班已经被";
            Employee employee= employeeMapper.selectByUserCode(user.getUserIdCode());
            if(employee!=null && StringUtils.isNotBlank(employee.getDeptCode())){
                zdUnitCode= zdUnitCodeService.queryByCode(employee.getDeptCode());
                message+="【"+zdUnitCode.getName()+"】【"+user.getUserName()+"】取消预约！";
            }
            messageService.sendWxMessage(createUser.getUserCode(),message);
        }
        return num;
    }

    @Override
    @Transactional(value = "thmzTransactionManager",propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public int rejectApplyScheduleOfMedical(ScheduleOfMedical scheduleOfMedical, User user){
        scheduleOfMedical.setStatus(ScheduleOfMedicalEnum.FREE.code);
        scheduleOfMedical.setUpdateDate(new Date());
        scheduleOfMedical.setUpdateId(user.getId());
        scheduleOfMedicalMapper.updateScheduleOfMedical(scheduleOfMedical);
        ScheduleOfMedicalApply  scheduleOfMedicalApply=scheduleOfMedicalApplyMapper.selectByScheduleId(scheduleOfMedical.getId());
        int num =0;
        if(scheduleOfMedicalApply!=null){
            num= scheduleOfMedicalApplyMapper.deleteScheduleOfMedicalApply(scheduleOfMedicalApply.getId());
        }
        ScheduleOfMedical dbScheduleOfMedical=scheduleOfMedicalMapper.selectScheduleOfMedicalById(scheduleOfMedical.getId());
        //发送取消预约提示消息
        User applyUser=userMapper.selectUserById(scheduleOfMedicalApply.getCreateId());
        //手机自助预约
        if (Constants.BRZZJF_CODE.equals(applyUser.getUserIdCode())){
            String reqNo= scheduleOfMedicalApply.getReqNo(scheduleOfMedicalApply.getActOrderNo());
            MzYjReq mzYjReq= mzYjReqService.queryMzYjReqByReqNo(reqNo);
            if(mzYjReq!=null){
                MzPatientMi mzPatientMi=mzPatientMiService.queryByPatientId(mzYjReq.getPatientId());
                String first= "对不起，您预约的时间无法为您提供检查服务，请点击详情自行预约其他检查时间或者退款";
                String jcxm="";
                if(StringUtils.isNotBlank(dbScheduleOfMedical.getJcxm())){
                    jcxm = dbScheduleOfMedical.getJcxm()+"预约申请失败通知";
                }
                String url = callBackYJYYUrl+reqNo+"&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
                haiCiAdapterService.commonMessageNotice(mzPatientMi.getIcCardNo(), "{\"data\":{\"first\":{\"color\":\"#FF0000\",\"value\":\""+first+"\"},\"keyword1\":{\"color\":\"#173177\",\"value\":\"" + jcxm + "\"},\"keyword2\":{\"color\":\"#173177\",\"value\":\""+mzPatientMi.getName()+"\"}},\"remark\":{\"color\":\"#FF0000\",\"value\":\"感谢你的使用！\"},\"miniprogram\":{\"appid\":\"\",\"pagepath\":\"\"},\"template_id\":\"mFlPZb1ohuxZXjJ75F83gd1lKPyaZjMb_RedHJmOkZM\",\"touser\":\"\",\"url\":\""+url+"\"}", new Date());
                haiCiAdapterService.rejectCallbackScheduleOfMedical(reqNo);
            }
            return num;
        }
        if(applyUser!=null && StringUtils.isNotBlank(applyUser.getUserCode())){
            ZdUnitCode zdUnitCode= zdUnitCodeService.queryByCode(dbScheduleOfMedical.getDepNo());
            String message= "您申请的科室【"+zdUnitCode.getName()+"】,日期【"+dbScheduleOfMedical.getRecordDate()+"】,开始时间【"+dbScheduleOfMedical.getBeginTime()+"】,结束时间【"+dbScheduleOfMedical.getEndTime()+"】对应的医技排班已经被";
            Employee employee= employeeMapper.selectByUserCode(user.getUserIdCode());
            if(employee!=null && StringUtils.isNotBlank(employee.getDeptCode())){
                zdUnitCode= zdUnitCodeService.queryByCode(employee.getDeptCode());
                message+="【"+zdUnitCode.getName()+"】【"+user.getUserName()+"】驳回，请及时关注！";
            }
            messageService.sendWxMessage(applyUser.getUserCode(),message);
        }
        return num;
    }

    @Override
    public List<String> queryDeptNos(ScheduleOfMedical scheduleOfMedical) {
        return scheduleOfMedicalMapper.selectDeptNos(scheduleOfMedical);
    }
}
