package thyyxxk.webserver.service.outpatient.thmz;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.dao.his.outpatient.thmz.MzEmrDao;
import thyyxxk.webserver.dao.his.zhuyuanyisheng.emr.EmrPatientDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.login.UserInfo;
import thyyxxk.webserver.entity.outpatient.thmz.MzEmrPatientData;
import thyyxxk.webserver.entity.outpatient.thmz.MzEmrPatientVo;
import thyyxxk.webserver.entity.outpatient.thmz.req.MzEmrAddDirReq;
import thyyxxk.webserver.entity.outpatient.thmz.req.MzEmrAddFileReq;
import thyyxxk.webserver.entity.outpatient.thmz.req.MzSaveFileReq;
import thyyxxk.webserver.service.externalhttp.emr.EmrEditor;
import thyyxxk.webserver.service.hutoolcache.DeptCache;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.service.zhuyuanyisheng.emr.EmrServer;
import thyyxxk.webserver.utils.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author:lihong
 * @Date: 2023/10/18
 */
@Service
@RequiredArgsConstructor
public class MzEmrService {
    private final MzEmrDao dao;
    private final EmrEditor emr;
    private final UserCache userCache;
    private final DeptCache deptCache;
    private final EmrPatientDao emrPatientDao;

    private final String mzDeptCode = "1400000";

    /**
     * @description:查询 1住院 2当前  3历史记录
     * @author: lihong
     * @date: 2023/10/18 16:51
     * @param: type
     * @return: java.util.Map<java.lang.String, java.util.List < com.alibaba.fastjson.JSONObject>>
     **/
    public List<MzEmrPatientData> queryMzEmrTree(MzEmrPatientVo param) {
        List<MzEmrPatientData> result;
        QueryWrapper<MzEmrPatientData> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pat_no", param.getPatientId());
        String strTemplate = "";
        List<MzEmrPatientData> list;
        if (param.getType() == 1) {
            String patNo = dao.selectPatNo(param.getPatientId());
            list = emrPatientDao.selectDataByPatNo(patNo);
            strTemplate = "第{}住院记录";
        } else if (param.getType() == 2) {
            queryWrapper.eq("times", param.getTimes());
            list = dao.selectList(queryWrapper);
            return list;
        } else {
            strTemplate = "第{}就诊记录";
            queryWrapper.ne("times", param.getTimes());
            list = dao.selectList(queryWrapper);
        }
        result = getTree(list, strTemplate);
        return result;
    }

    private List<MzEmrPatientData> getTree(List<MzEmrPatientData> list, String strTemplate) {
        if (CollUtil.isEmpty(list)) return list;
        List<MzEmrPatientData> result = new ArrayList<>();
        Map<Integer, List<MzEmrPatientData>> collect = list.stream().collect(Collectors.groupingBy(MzEmrPatientData::getTimes));
        int index = 1;
        for (Integer key : collect.keySet()) {
            MzEmrPatientData tem = new MzEmrPatientData();
            tem.setId(index);
            tem.setName(StrUtil.format(strTemplate, key));
            tem.setChildren(collect.get(key));
            result.add(tem);
        }
        return result;
    }

    public ResultVo<String> saveMzEmrModel(MzEmrPatientData param) {
        AssertUtil.isnotBlank(param.getEmrDocumentId(), "文档id不能为空");
        AssertUtil.isnotBlank(param.getUserIdCode(), "用户不能为空");
        JSONObject saveJson = new JSONObject();
        saveJson.put("document", param.getDocumentData());
        try {
            emr.saveDocument(saveJson);
        } catch (Exception e) {
            return ResultVoUtil.fail(ExceptionEnum.EMR_SAVE, "病历保存错误，请重试！" + e.getMessage());
        }
        QueryWrapper<MzEmrPatientData> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("emr_document_id", param.getEmrDocumentId());
        MzEmrPatientData mzEmrPatientData = dao.selectOne(queryWrapper);
        if (mzEmrPatientData == null) {
            param.setCreateId(param.getUserIdCode());
            dao.insert(param);
        } else {
            param.setModifyId(param.getUserIdCode());
            param.setModifyDate(new Date());
            UpdateWrapper<MzEmrPatientData> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("emr_document_id", param.getEmrDocumentId());
            dao.update(param, updateWrapper);
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "保存成功");
    }


    public JSONArray getMzEmrModel() {
        return emr.getDeptList(mzDeptCode);
    }

    public ResultVo< List<JSONObject>> getSnippet() {
        JSONArray data = emr.getSnippetByDept(mzDeptCode);
        List<JSONObject> tree = new ArrayList<>();
        EmrServer.emrArrToTree(data, tree);
        return R.ok(tree);
    }

    public MzEmrPatientVo queryMzPatientInfo(MzEmrPatientVo param) {
        AssertUtil.isnotBlank(param.getPatientId(), "门诊号不能为空");
        MzEmrPatientVo data = dao.selectMzEmrPatientVo(param);
        if (StrUtil.isNotBlank(param.getUserIdCode())) {
            UserInfo userInfo = userCache.get(param.getUserIdCode());
            data.setUserName(userCache.getEmployeeName(param.getUserIdCode()));
            data.setDeptCode(userInfo.getDeptCode());
            data.setDeptName(deptCache.getDeptName(userInfo.getDeptCode()));
        }
        if (data.getAge() == null) {
            if (data.getBirthDay() != null) {
                data.setAge(DateUtil.age(data.getBirthDay(), null));
            } else {
                data.setAge(DateUtil.age(IdcardUtil.getBirthDate(data.getSocialNo()), null));
            }
        }
        data.setPatientId(param.getPatientId());
        data.setTimes(param.getTimes());
        data.setUserIdCode(param.getUserIdCode());
        BeanUtil.trimStrFields(data);
        return data;
    }

    private LambdaQueryWrapper<MzEmrPatientData> getQueryWrapper(String patientNo, Integer times) {
        LambdaQueryWrapper<MzEmrPatientData> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MzEmrPatientData::getPatNo, patientNo);
        queryWrapper.eq(MzEmrPatientData::getTimes, times);
        return queryWrapper;
    }

    public ResultVo<List<MzEmrPatientData>> getEmrModelByPatientId(String patientNo, Integer times) {
        List<MzEmrPatientData> mzEmrFolder = dao.getMzEmrFolder();
        LambdaQueryWrapper<MzEmrPatientData> queryWrapper = getQueryWrapper(patientNo, times);
        queryWrapper.eq(MzEmrPatientData::getDelFlag, 0);
        List<MzEmrPatientData> mzEmrPatientData = dao.selectMyList(queryWrapper);
        mzEmrFolder.addAll(mzEmrPatientData);

        List<MzEmrPatientData> execute = TreeUtilV2
                .create(mzEmrFolder)
                .id("emrDocumentId")
                .children("children")
                .parentId("parent").execute();

        return R.ok(execute);
    }

    public ResultVo<String> addDir(MzEmrAddDirReq value) {
        MzEmrPatientData data = new MzEmrPatientData();
        data.setName(value.getName());
        data.setEmrName(value.getName());
        data.setEmrCategoryCode(EmrServer.THIS_IS_DIR);
        data.setEmrDocumentId(SnowFlakeId.instance().nextId());
        data.setParent(value.getParent());
        data.setPatNo(value.getPatientId());
        data.setTimes(value.getTimes());
        data.setCreateId(TokenUtil.getInstance().getTokenUserId());
        dao.insert(data);
        return R.ok(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<MzEmrPatientData> addFile(MzEmrAddFileReq value) {
        String id = SnowFlakeId.instance().nextId();
        JSONObject document = value.getDocument();
        // 设置id，这里不用在包裹一层 document 了，前端包裹了，但是需要设置id
        document.getJSONObject("document").put("_id", id);
        try {
            emr.saveDocument(document);
        } catch (Exception e) {
            return ResultVoUtil.fail(ExceptionEnum.EMR_SAVE, "病历保存错误，请重试！" + e.getMessage());
        }
        MzEmrPatientData insert = MzEmrPatientData.builder()
                .emrCategoryCode(value.getEmrCategoryCode())
                .name(value.getName())
                .emrName(value.getName())
                .createId(TokenUtil.getInstance().getTokenUserId())
                .parent(value.getParent())
                .patNo(value.getPatientId())
                .times(value.getTimes())
                .emrDocumentId(id)
                .build();
        dao.insert(insert);
        return R.ok(insert);
    }

    public ResultVo<String> updateFile(MzSaveFileReq value) {
        MzEmrPatientData mzEmrPatientData = dao.selectById(value.getEmrDocumentId());
        if (mzEmrPatientData == null) {
            return R.fail(ExceptionEnum.LOGICAL_ERROR, "病历不存在。");
        }
        if (!mzEmrPatientData.getCreateId().equals(TokenUtil.getInstance().getTokenUserId())) {
            return R.fail(ExceptionEnum.LOGICAL_ERROR, "创建人不是您无法删除。");
        }
        if (mzEmrPatientData.getEmrPrint()) {
            return R.fail(ExceptionEnum.LOGICAL_ERROR, "病历已打印无法修改。");
        }
        try {
            emr.saveDocument(value.getDocument());
        } catch (Exception e) {
            return ResultVoUtil.fail(ExceptionEnum.EMR_SAVE, "病历保存错误，请重试！" + e.getMessage());
        }
        MzEmrPatientData build = MzEmrPatientData.builder()
                .emrDocumentId(value.getEmrDocumentId())
                .modifyDate(new Date())
                .modifyId(TokenUtil.getInstance().getTokenUserId())
                .emrDataElement(value.getEmrDataElement())
                .build();

        dao.updateById(build);
        return R.ok(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<String> delFile(String documentId) {
        MzEmrPatientData mzEmrPatientData = dao.selectById(documentId);
        if (mzEmrPatientData == null) {
            return R.fail(ExceptionEnum.LOGICAL_ERROR, "病历不存在。");
        }
        if (!mzEmrPatientData.getCreateId().equals(TokenUtil.getInstance().getTokenUserId())) {
            return R.fail(ExceptionEnum.LOGICAL_ERROR, "创建人不是您无法删除。");
        }
        int i = dao.deleteById(documentId);
        if (i > 0) {
            return R.ok(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
        }
        return R.fail(ExceptionEnum.LOGICAL_ERROR, "删除失败。");
    }

    public ResultVo<List<MzEmrPatientData>> getRecycleBinMedicalRecords(String patientNo, Integer times) {
        LambdaQueryWrapper<MzEmrPatientData> queryWrapper = getQueryWrapper(patientNo, times);
        queryWrapper.eq(MzEmrPatientData::getCreateId, TokenUtil.getInstance().getTokenUserId());
        queryWrapper.eq(MzEmrPatientData::getDelFlag, 1);
        queryWrapper.ne(MzEmrPatientData::getEmrCategoryCode, EmrServer.THIS_IS_DIR);
        return R.ok(dao.selectMyList(queryWrapper));
    }

    public ResultVo<String> restoreMedicalRecords(String documentId) {
        int i = dao.restoreMedicalRecords(documentId);
        if (i > 0) {
            return R.ok(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
        }
        return R.fail(ExceptionEnum.LOGICAL_ERROR, "恢复失败。");
    }

    public ResultVo<List<MzEmrPatientData>> getHistoryTimes(String patientNo, Integer times) {
        LambdaQueryWrapper<MzEmrPatientData> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MzEmrPatientData::getPatNo, patientNo);
        queryWrapper.ne(MzEmrPatientData::getTimes, times);
        queryWrapper.eq(MzEmrPatientData::getDelFlag, 0);
        queryWrapper.ne(MzEmrPatientData::getEmrCategoryCode, EmrServer.THIS_IS_DIR);
        return R.ok(dao.selectMyList(queryWrapper));
    }

    public ResultVo<String> print(String documentId) {
        UpdateWrapper<MzEmrPatientData> queryWrapper = new UpdateWrapper<>();
        queryWrapper.set("emr_print", true);
        queryWrapper.eq("emr_document_id", documentId);
        dao.update(queryWrapper);
        return R.ok();
    }


    public ResultVo<String> endOfVisit(String patientNo, Integer times) {
        int i = dao.endOfVisit(patientNo, times, TokenUtil.getInstance().getTokenUserId());
        if (i > 0) {
            return R.ok(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
        }
        return R.fail(ExceptionEnum.LOGICAL_ERROR, "操作失败，可能原因就诊医生不是您，或者已经完成了结束就诊了。");
    }


}
