package cn.hnthyy.thmz.controller.mz;

import cn.hnthyy.thmz.Utils.CloneUtil;
import cn.hnthyy.thmz.Utils.DateUtil;
import cn.hnthyy.thmz.Utils.TokenUtil;
import cn.hnthyy.thmz.comment.UserLoginToken;
import cn.hnthyy.thmz.entity.his.mz.Employee;
import cn.hnthyy.thmz.entity.his.mz.MzyRequest;
import cn.hnthyy.thmz.entity.his.mz.MzyZdChargeType;
import cn.hnthyy.thmz.entity.his.zd.ZdUnitCode;
import cn.hnthyy.thmz.entity.thmz.User;
import cn.hnthyy.thmz.service.his.mz.EmployeeService;
import cn.hnthyy.thmz.service.his.mz.MzyRequestService;
import cn.hnthyy.thmz.service.his.mz.MzyZdChargeTypeService;
import cn.hnthyy.thmz.service.his.zd.ZdUnitCodeService;
import cn.hnthyy.thmz.pageDto.EmployeePageDto;
import cn.hnthyy.thmz.vo.RequestParamsVo;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
public class MzyRequestController {
    @Autowired
    private MzyRequestService mzyRequestService;
    @Autowired
    private ZdUnitCodeService zdUnitCodeService;
    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private MzyZdChargeTypeService mzyZdChargeTypeService;

    /**
     * 按日期和时间区间查询可以挂号的科室
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getUnitCodeByRequestDay", method = {RequestMethod.GET, RequestMethod.POST})
    public Map<String, Object> getUnitCodeByRequestDay(@RequestParam("ampm") String ampm) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (StringUtils.isBlank(ampm)) {
                resultMap.put("code", -1);
                resultMap.put("message", "挂号时间区间不能为空");
                return resultMap;
            }
            List<String> unitCodes = mzyRequestService.queryUnitCodeByRequestDay(DateFormatUtils.format(new Date(), "yyyy-MM-dd"), ampm);
            List<ZdUnitCode> data = new ArrayList<>();
            if (unitCodes != null && unitCodes.size() > 0) {
                unitCodes.forEach(u -> {
                    if (StringUtils.isNotBlank(u)) {
                        ZdUnitCode zdUnitCode = zdUnitCodeService.queryByCode(u);
                        if (zdUnitCode != null) {
                            data.add(zdUnitCode);
                        }
                    }
                });
            }
            resultMap.put("code", 0);
            resultMap.put("message", "按日期和时间区间查询可以挂号的科室成功");
            resultMap.put("data", data);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("按日期和时间区间查询可以挂号的科室失败，错误信息{}", e.getMessage());
            resultMap.put("code", -1);
            resultMap.put("message", "按日期和时间区间查询可以挂号的科室失败");
            return resultMap;
        }
    }

    /**
     * 按日期和时间区间以及部门编码查询可以挂号的号别
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getChargeTypeByRequestDay", method = {RequestMethod.GET, RequestMethod.POST})
    public Map<String, Object> getChargeTypeByRequestDay(@RequestParam("unitCode") String unitCode, @RequestParam("ampm") String ampm) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (StringUtils.isBlank(unitCode)) {
                resultMap.put("code", -1);
                resultMap.put("message", "挂号科室不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(ampm)) {
                resultMap.put("code", -1);
                resultMap.put("message", "挂号时间区间不能为空");
                return resultMap;
            }
            resultMap.put("code", 0);
            resultMap.put("message", "按日期和时间区间以及部门编码查询可以挂号的号别成功");
            resultMap.put("data", mzyRequestService.queryChargeTypeByRequestDay(DateFormatUtils.format(new Date(), "yyyy-MM-dd"), unitCode, ampm));
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("按日期和时间区间以及部门编码查询可以挂号的号别失败，错误信息{}", e.getMessage());
            resultMap.put("code", -1);
            resultMap.put("message", "按日期和时间区间以及部门编码查询可以挂号的号别失败");
            return resultMap;
        }
    }


    /**
     * 按日期和时间区间医技科室id查询可以挂号的医生
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getDoctorCodeByRequestDay", method = {RequestMethod.GET, RequestMethod.POST})
    public Map<String, Object> getDoctorCodeByRequestDay(@RequestParam("unitCode") String unitCode, @RequestParam("ampm") String ampm, @RequestParam("chargeType") String chargeType) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (StringUtils.isBlank(unitCode)) {
                resultMap.put("code", -1);
                resultMap.put("message", "挂号科室不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(ampm)) {
                resultMap.put("code", -1);
                resultMap.put("message", "挂号时间区间不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(chargeType)) {
                resultMap.put("code", -1);
                resultMap.put("message", "号别不能为空");
                return resultMap;
            }
            List<MzyRequest> mzyRequests = mzyRequestService.queryDoctorCodeByRequestDay(DateFormatUtils.format(new Date(), "yyyy-MM-dd"), unitCode, ampm, chargeType);
            List<EmployeePageDto> data = new ArrayList<>();
            if (mzyRequests != null && mzyRequests.size() > 0) {
                mzyRequests.forEach(d -> {
                    if (d != null) {
                        Employee employee;
                        if (StringUtils.isNotBlank(d.getDoctorCode())) {
                            employee = employeeService.queryByUserCode(d.getDoctorCode());
                            if (employee == null) {
                                log.error("没有查询到对应的医生，医生编码是{}", d.getDoctorCode());
                                employee = new Employee();
                                employee.setEmployeeCode(d.getDoctorCode());
                                employee.setEmployeeName(d.getDoctorCode());
                            }
                        } else {
                            employee = new Employee();
                            employee.setEmployeeCode("-1");
                            employee.setEmployeeName("无需选择医生");
                        }
                        if (employee != null) {
                            EmployeePageDto employeePageDto = new EmployeePageDto();
                            employeePageDto.setEmployee(employee);
                            employeePageDto.setChargeType(d.getChargeType());
                            employeePageDto.setCheckFee(d.getCheckFee());
                            employeePageDto.setMzyRequestId(d.getId());
                            employeePageDto.setLeftNum(d.getLeftNum());
                            data.add(employeePageDto);
                        }
                    }
                });
            }
            resultMap.put("code", 0);
            resultMap.put("message", "按日期和时间区间医技科室id查询可以挂号的医生成功");
            resultMap.put("data", data);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("按日期和时间区间医技科室id查询可以挂号的医生失败，错误信息{}", e.getMessage());
            resultMap.put("code", -1);
            resultMap.put("message", "按日期和时间区间医技科室id查询可以挂号的医生失败");
            return resultMap;
        }
    }


    /**
     * 根据时间范围查询号标数据
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getRequestByTimes", method = {RequestMethod.POST})
    public Map<String, Object> getRequestByTimes(@RequestBody RequestParamsVo requestParamsVo) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (requestParamsVo == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "根据时间范围查询号标数据失败,参数为空");
                return resultMap;
            }
            if(StringUtils.isBlank(requestParamsVo.getUnitCode())){
                requestParamsVo.setUnitCode(null);
            }
            if(StringUtils.isBlank(requestParamsVo.getAmpm())){
                requestParamsVo.setAmpm(null);
            }
            resultMap.put("code", 0);
            resultMap.put("message", "根据时间范围查询号标数据成功");
            List<MzyRequest> mzyRequests = mzyRequestService.queryByTimes(requestParamsVo.getBeginDate(), requestParamsVo.getEndDate(),requestParamsVo.getUnitCode(),requestParamsVo.getAmpm());
            fitRequest(mzyRequests);
            resultMap.put("data", mzyRequests);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("根据时间范围查询号标数据失败，错误信息{}", e.getMessage());
            resultMap.put("code", -1);
            resultMap.put("message", "根据时间范围查询号标数据失败");
            return resultMap;
        }
    }


    /**
     * 保存号表数据
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/saveRequest", method = {RequestMethod.POST})
    public Map<String, Object> saveRequest(@RequestBody RequestParamsVo requestParamsVo, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (requestParamsVo == null || requestParamsVo.getMzyRequests() == null || requestParamsVo.getMzyRequests().size() == 0) {
                resultMap.put("code", -1);
                resultMap.put("message", "保存号表数据失败,参数为空");
                return resultMap;
            }
            User tokenUser = TokenUtil.getUser(httpServletRequest);
            resultMap.put("code", 0);
            resultMap.put("message", "保存号表数据成功");
            mzyRequestService.saveRequest(requestParamsVo.getMzyRequests(), tokenUser.getUserIdCode());
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("保存号表数据失败，错误信息{}", e.getMessage());
            resultMap.put("code", -1);
            if(e.getMessage().contains("不能在具有唯一索引")){
                resultMap.put("message", "新增的号表信息重复");
                return resultMap;
            }
            resultMap.put("message", "保存号表数据失败，错误信息："+e.getMessage());
            return resultMap;
        }
    }


    /**
     * 根据源号表数据模板创建新的号表数据
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getNewRequestByTimes", method = {RequestMethod.POST})
    public Map<String, Object> getNewRequestByTimes(@RequestBody RequestParamsVo requestParamsVo) {
        Map<String, Object> resultMap = new HashMap<>();
        List<MzyRequest> newMzyRequest = new ArrayList<>();
        resultMap.put("data", newMzyRequest);
        try {
            if (requestParamsVo == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "根据源号表数据模板创建新的号表数据失败,参数为空");
                return resultMap;
            }
            if (requestParamsVo.getBeginDate() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "根据源号表数据模板创建新的号表数据失败,源数据开始时间为空");
                return resultMap;
            }
            if (requestParamsVo.getEndDate() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "根据源号表数据模板创建新的号表数据失败,源数据结束时间为空");
                return resultMap;
            }
            if (requestParamsVo.getNewBeginDate() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "根据源号表数据模板创建新的号表数据失败,新号表开始时间为空");
                return resultMap;
            }
            if (requestParamsVo.getNewEndDate() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "根据源号表数据模板创建新的号表数据失败,新号表结束时间为空");
                return resultMap;
            }
            if (requestParamsVo.getNewBeginDate().before(requestParamsVo.getEndDate())) {
                resultMap.put("code", -1);
                resultMap.put("message", "根据源号表数据模板创建新的号表数据失败,新号表开始时间必须晚于已有号表的结束时间");
                return resultMap;
            }
            List<MzyRequest> mzyRequests = mzyRequestService.queryByTimes(requestParamsVo.getBeginDate(), requestParamsVo.getEndDate(),null,null);
            if (mzyRequests==null || mzyRequests.size()==0){
                resultMap.put("code", -1);
                resultMap.put("message", "根据源号表数据模板创建新的号表数据失败,源号表不存在");
                return resultMap;
            }
            //获取新号表的日期集合
            requestParamsVo.setNewEndDate(DateUtil.getFirstSecond(requestParamsVo.getNewEndDate()));
            List<Date> days = DateUtil.getBetweenDates(requestParamsVo.getNewBeginDate(), requestParamsVo.getNewEndDate());
//            //如果新号表日期集合不包含当前日期，加入当前日期
//            if (!days.contains(requestParamsVo.getNewBeginDate())) {
//                List<Date> tempDays = new ArrayList<>(days.size()+1);
//                tempDays.add(requestParamsVo.getNewBeginDate());
//                tempDays.addAll(days);
//                days=tempDays;
//            }
            //原号表日期与号表映射
            Map<Date, List<MzyRequest>> sourceMap = new HashMap<>();
            //源号表日期集合
            List<Date> sourceDate = new ArrayList<>();
            for (MzyRequest m : mzyRequests) {
                if (!sourceDate.contains(m.getRequestDay())) {
                    sourceDate.add(m.getRequestDay());
                    sourceMap.put(m.getRequestDay(), new ArrayList<>());
                }
                List<MzyRequest> temp = sourceMap.get(m.getRequestDay());
                temp.add(m);
            }
            for (int i = 0; i < days.size(); i++) {
                //因为新号表按照源号表的顺序依次替换，所以取余
                Date key = sourceDate.get(i % sourceDate.size());
                List<MzyRequest> oneDateList = sourceMap.get(key);
                for (MzyRequest o : oneDateList) {
                    MzyRequest mrc = CloneUtil.clone(o);
                    mrc.setRequestDay(days.get(i));
                    mrc.setLeftNum(30);
                    mrc.setTotalNum(30);
                    newMzyRequest.add(mrc);
                }
            }
            resultMap.put("code", 0);
            resultMap.put("message", "根据源号表数据模板创建新的号表数据成功");
            fitRequest(newMzyRequest);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("根据源号表数据模板创建新的号表数据失败，错误信息{}", e.getMessage());
            resultMap.put("code", -1);
            resultMap.put("message", "根据源号表数据模板创建新的号表数据失败");
            return resultMap;
        }
    }


    /**
     * 将新增的单条号表数据保存到临时数据后格式化数据并返回
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/formatRequest", method = {RequestMethod.POST})
    public Map<String, Object> formatRequest(@RequestBody RequestParamsVo requestParamsVo) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (requestParamsVo == null || requestParamsVo.getMzyRequests() == null || requestParamsVo.getMzyRequests().size() == 0) {
                resultMap.put("code", -1);
                resultMap.put("message", "格式化临时号表失败,参数为空");
                return resultMap;
            }
            fitRequest(requestParamsVo.getMzyRequests());
            resultMap.put("code", 0);
            resultMap.put("message", "格式化临时号表成功");
            resultMap.put("data", requestParamsVo.getMzyRequests());
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("格式化临时号表失败，错误信息{}", e.getMessage());
            resultMap.put("code", -1);
            resultMap.put("message", "格式化临时号表失败");
            return resultMap;
        }
    }


    /**
     * 根据号表id查询号表
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getRequestById", method = {RequestMethod.GET})
    public Map<String, Object> getRequestById(@RequestParam("id") Long id) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (id==null) {
                resultMap.put("code", -1);
                resultMap.put("message", "号表id不能为空");
                return resultMap;
            }
            MzyRequest mzyRequest=mzyRequestService.queryById(id);
            resultMap.put("code", 0);
            resultMap.put("message", "根据号表id查询号表成功");
            resultMap.put("data", mzyRequest);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("根据号表id查询号表失败，错误信息{}", e.getMessage());
            resultMap.put("code", -1);
            resultMap.put("message", "根据号表id查询号表失败");
            return resultMap;
        }
    }


    private void fitRequest(List<MzyRequest> newMzyRequest) {
        List<MzyZdChargeType> mzyZdChargeTypes = mzyZdChargeTypeService.queryAllMzyZdChargeType();
        Map<String, String> mzyZdChargeTypeMap = null;
        if (mzyZdChargeTypes != null) {
            mzyZdChargeTypeMap = mzyZdChargeTypes.stream().collect(Collectors.toMap(MzyZdChargeType::getCode, MzyZdChargeType::getName));
        }
        Map<String, String> finalMzyZdChargeTypeMap = mzyZdChargeTypeMap;
        newMzyRequest.stream().forEach(m -> {
            if (StringUtils.isNotBlank(m.getUnitCode())) {
                String unitName = zdUnitCodeService.queryDeptNameByIdInCache(m.getUnitCode());
                if (StringUtils.isNotBlank(unitName)) {
                    m.setUnitName(unitName);
                }
            }
            if (StringUtils.isNotBlank(m.getDoctorCode())) {
                Employee employee = employeeService.queryByUserCode(m.getDoctorCode());
                if (employee != null) {
                    m.setDoctorName(employee.getEmployeeName());
                }
            }
            if (finalMzyZdChargeTypeMap != null) {
                String chargeType = finalMzyZdChargeTypeMap.get(m.getChargeType());
                m.setChargeTypeName(chargeType == null ? "" : chargeType);
            }
            if(m.getRequestDay()!=null){
                m.setRequestDay(DateUtil.getFirstSecond(m.getRequestDay()));
            }
        });
    }




    /**
     * 根据号表id删除号表
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/deleteRequestById", method = {RequestMethod.GET})
    public Map<String, Object> deleteRequestById(@RequestParam("id") Long id) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (id==null) {
                resultMap.put("code", -1);
                resultMap.put("message", "号表id不能为空");
                return resultMap;
            }
            mzyRequestService.removeMzyRequestById(id);
            resultMap.put("code", 0);
            resultMap.put("message", "根据号表id删除号表成功");
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("根据号表id删除号表失败，错误信息{}", e.getMessage());
            resultMap.put("code", -1);
            resultMap.put("message", "根据号表id删除号表失败");
            return resultMap;
        }
    }


    /**
     * 根据排班主键和生日查询挂号费用
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getMzChargeTypeByMzyRequestId", method = {RequestMethod.GET})
    public Map<String, Object> getMzChargeTypeByMzyRequestId(@RequestParam("mzyRequestId") Long mzyRequestId,@RequestParam("birthDay") String birthDay) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (mzyRequestId==null) {
                resultMap.put("code", -1);
                resultMap.put("message", "排班主键不能为空");
                return resultMap;
            }
            Date birthDayD =null;
            if (StringUtils.isNotBlank(birthDay)) {
                birthDayD= DateUtil.pase(birthDay,"yyyy-MM-dd");
            }
            MzyZdChargeType mzyZdChargeType=mzyRequestService.calculateAddition(mzyRequestId,birthDayD);
            resultMap.put("code", 0);
            resultMap.put("message", "根据排班主键和生日查询挂号费用成功");
            resultMap.put("data", mzyZdChargeType);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("根据排班主键和生日查询挂号费用失败，错误信息{}", e.getMessage());
            resultMap.put("code", -1);
            resultMap.put("message", "根据排班主键和生日查询挂号费用失败");
            return resultMap;
        }
    }

}
