package thyyxxk.webserver.service.zhuyuanyisheng;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.YesOrNo;
import thyyxxk.webserver.dao.his.zhuyuanyisheng.CaoYaoYiZhuDao;
import thyyxxk.webserver.dao.his.zhuyuanyisheng.YiZhuLuRuDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.datamodify.GetDropdownBox;
import thyyxxk.webserver.entity.login.UserInfo;
import thyyxxk.webserver.entity.zhuyuanyisheng.caoyaoyizhu.CaoYaoChaXunTiaoJian;
import thyyxxk.webserver.entity.zhuyuanyisheng.caoyaoyizhu.YzActOrderCy;
import thyyxxk.webserver.entity.zhuyuanyisheng.caoyaoyizhu.YzActOrderCyDetail;
import thyyxxk.webserver.entity.zhuyuanyisheng.caoyaoyizhu.YzOrderPatternCy;
import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.XinZhenYiZhu;
import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.XinZhenYzActOrder;
import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.YiZhuMingChen;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.utils.*;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 描述：
 * </p>
 *
 * @author xc
 * @date 2022-02-26 08:39
 */
@Service
@Slf4j
public class CaoYaoYiZhuService {
    private final CaoYaoYiZhuDao dao;
    private final PublicServer publicServer;
    private final YiZhuLuRuDao yiZhuLuRuDao;
    private final YiZhuLuRuServer yiZhuLuRuServer;

    @Getter
    public enum CaoYaoEnumStatusFlag {
        申请退药("T"),
        删除("d"),
        收费("2"),
        配药中("3");

        private final String flag;

        CaoYaoEnumStatusFlag(String flag) {
            this.flag = flag;
        }
    }

    public CaoYaoYiZhuService(CaoYaoYiZhuDao dao,
                              PublicServer publicServer,
                              YiZhuLuRuDao yiZhuLuRuDao,
                              YiZhuLuRuServer yiZhuLuRuServer) {
        this.dao = dao;
        this.publicServer = publicServer;
        this.yiZhuLuRuDao = yiZhuLuRuDao;
        this.yiZhuLuRuServer = yiZhuLuRuServer;
    }

    public ResultVo<List<YzActOrderCy>> huoQuCaoYaoShuJu(CaoYaoChaXunTiaoJian param) {
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.eq("inpatient_no", param.getPatNo());
        qw.eq("admiss_times", param.getTimes());
        qw.orderByDesc("input_date");
        if (StringUtil.notBlank(param.getStartTime())) {
            qw.ge("input_date", param.getStartTime());
            qw.le("input_date", param.getEndTime());
        }
        List<YzActOrderCy> list = dao.huoQuCaoYaoShuJu(qw);
        if (ListUtil.notBlank(list)) {
            for (YzActOrderCy item : list) {
                item.setDaiJianFei(item.getQuantityDj().multiply(item.getOrderJeDj()));
                item.setJiaGe(item.getQuantity().multiply(item.getOrderJe()));
                item.setZongJia(item.getDaiJianFei().add(item.getJiaGe()));
            }
        }
        return ResultVoUtil.success(list);
    }

    public ResultVo<List<YzActOrderCyDetail>> huoQuChaoYaoMingXi(BigDecimal orderNo) {
        return ResultVoUtil.success(dao.huoQuChaoYaoMingXi(orderNo));
    }

    public ResultVo<List<GetDropdownBox>> fuYongFangFa() {
        return ResultVoUtil.success(dao.fuYongFangFa());
    }

    public ResultVo<List<YiZhuMingChen>> huoQuCaoYao(String queryName, Integer groupNo) {
        String name = StringUtil.englishToCapital(queryName);
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.and(q -> q
                        .like("py_code", name)
                        .or()
                        .like("name", name)
                        .or()
                        .like("d_code", name)
                        .or()
                        .like("code", name)
                )
                .eq("group_no", groupNo);
        return ResultVoUtil.success(dao.huoQuCaoYao(qw));
    }


    public ResultVo<IPage<YzOrderPatternCy>> huoQuMuBan(String queryName, String deptCode, long currentPage, long pageSize, long total) {
        IPage<YzOrderPatternCy> page = new Page<>(currentPage, pageSize, total == 0);
        String name = StringUtil.englishToCapital(queryName);
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.and(q -> q
                .like("py_code", name)
                .or()
                .like("d_code", name)
                .or()
                .like("pattern_name", name)
        );
        qw.groupBy("pattern_name");
        dao.huoQuMuBan(page, qw);
        return ResultVoUtil.success(page);
    }

    public ResultVo<List<YzOrderPatternCy>> muBanXiangQing(String name, String deptCode) {
        return ResultVoUtil.success(dao.muBanXiangQing(name, deptCode));
    }

    public ResultVo<Boolean> chongFuMuBanMing(String name) {
        return ResultVoUtil.success(dao.chongFuMuBanMing(name) > 1);
    }

    public ResultVo<String> cunMuBan(YzOrderPatternCy param) {
        log.info("插入模板草药模板：{}", JSON.toJSONString(param));
        String py = PingYinUtils.pyShouZiMuDaXie(param.getPatternName());
        if (py.length() > 7) {
            py = py.substring(0, 7);
        }
        String wb = PingYinUtils.getWBCode(param.getPatternName());
        if (wb.length() > 7) {
            wb = wb.substring(0, 7);
        }

        dao.chaRuMuBan(param.getList(), param.getPatternName(),
                TokenUtil.getInstance().getTokenUserId(), py, wb,
                param.getDeptCode());
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<Map<String, List<String>>> baoCunCaoYao(YzActOrderCy param) {
        if (ListUtil.isBlank(param.getList())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请先选择需要上传的数据。");
        }
        // 药品 code
        Set<String> yaoPingCode = new HashSet<>(param.getList().size());
        publicServer.huanZheJieSuan(param.getInpatientNo(), param.getAdmissTimes());
        BigDecimal sum = new BigDecimal(0);
        for (YzActOrderCyDetail item : param.getList()) {
            sum = sum.add(item.getQuantity().multiply(item.getRetprice()));
            yaoPingCode.add(item.getChargeCode().trim() + item.getSerial().trim() + item.getGroupNo().trim());
        }
        XinZhenYiZhu patInfo = yiZhuLuRuDao.queryPatientInfo(param.getInpatientNo(), param.getAdmissTimes());
        Map<String, XinZhenYzActOrder> drug = yiZhuLuRuServer.getDrugInformation(yaoPingCode, patInfo.getZkWard());
        // 错误信息
        Map<String, List<String>> errorMap = new HashMap<>(param.getList().size());
        // 获取医生开药品的权限
        UserInfo userInfo = yiZhuLuRuDao.selectedUserInfoByCode(TokenUtil.getInstance().getTokenUserId());
        for (int i = 0; i < param.getList().size(); i++) {
            YzActOrderCyDetail item = param.getList().get(i);
            XinZhenYzActOrder feiYongXinXi = drug.get(item.getChargeCode().trim() + item.getSerial().trim() + item.getGroupNo().trim());
            List<String> errorMessage = limitation(feiYongXinXi, userInfo, item);
            if (ListUtil.notBlank(errorMessage)) {
                errorMap.put("第" + (i + 1) + "个，名称：" + item.getChargeCodeName(), errorMessage);
            }
        }
        if (!errorMap.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.ERROR_MESSAGE, "请修改有错误的数据。", errorMap);
        }
        param.setOrderJe(sum);
        param.setInputId(TokenUtil.getInstance().getTokenUserId());
        // 设置代煎费
        param.setOrderJeDj(dao.huoQuDaiJianFei());
        param.setPageNo(publicServer.getTheDrugListNo());
        XinZhenYiZhu huanZheXinXi = yiZhuLuRuDao.queryPatientInfo(param.getInpatientNo(), param.getAdmissTimes());
        param.setOrderNo(publicServer.getActOrderNo());
        try {
            // 生成草药和医嘱
            generateHerbs(param, huanZheXinXi);
        } catch (Exception e) {
            log.error("插入草药错误:{}", e.getMessage());
            dao.manualTransactions(param.getInpatientNo(), param.getAdmissTimes(), param.getOrderNo());
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, e.getMessage());
        }
        List<String> content = new ArrayList<>();
        content.add(String.format("草药医嘱名：<span style='color:#409eff'>【%s】</span><br>" +
                "剂数：<span style='color:#409eff'>【%s】</span><br>" +
                "患者名：<span style='color:#409eff'>【%s】<br></span>" +
                "床位：<span style='color:#409eff'>【%s】</span>", param.getOrderName(), param.getQuantity().toString(), huanZheXinXi.getName(), huanZheXinXi.getBedNo()));
        try {
            publicServer.faSongXiaoXi(huanZheXinXi, content, "新增草药或颗粒医嘱", TokenUtil.getInstance().getTokenUserId());
        } catch (Exception ignore) {
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public void generateHerbs(YzActOrderCy param, XinZhenYiZhu huanZheXinXi) {
        dao.chaRuCaoYaoYiZhu(param, huanZheXinXi.getDeptCode(), huanZheXinXi.getDeptCode(), param.getExecDept());
        dao.chaRuCaoYaoXiangQing(param.getList(), param.getOrderNo());
        String orderName = param.getGroupNo().equals("81") ?
                "草药医嘱:" :
                "草药颗粒医嘱:" + param.getOrderName() + param.getQuantity() + "剂";
        dao.chaRuYiZhu(param, orderName,
                huanZheXinXi.getDeptCode(),
                huanZheXinXi.getDeptCode(),
                param.getExecDept(),
                PublicServer.getInfantFlag(huanZheXinXi.getInpatientNo()));
    }

    @NotNull
    private static List<String> limitation(XinZhenYzActOrder feiYongXinXi,
                                           UserInfo us,
                                           YzActOrderCyDetail item) {
        List<String> errorMessage = new ArrayList<>();
        if (feiYongXinXi == null) {
            errorMessage.add("没有找到药品信息，请联系药剂药房。");
        } else {
            if (feiYongXinXi.getDelFlag() == 1) {
                errorMessage.add("药品已经被停用了，请联系药剂科");
            }
            if (feiYongXinXi.getYpLevel() > us.getDoctorLevel()) {
                errorMessage.add("您没有开此药品的权限");
            }
            if (!"028".equals(feiYongXinXi.getBillItemZy()) && !YesOrNo.YES.getCode().equals(us.getDoctorZy())) {
                errorMessage.add("您没有开此药品的权限，请联系医务部。");
            }
            if (BigUtils.bigDaYu(item.getQuantity(), feiYongXinXi.getStockAmount())) {
                errorMessage.add("药品领量大于药品的库存，当前库存量" + feiYongXinXi.getStockAmount().stripTrailingZeros().toPlainString());
            }
            if (feiYongXinXi.getDeptRestrictions() > 0) {
                errorMessage.add("该药品禁止在患者所在的科室使用。");
            }
            if (feiYongXinXi.getVisibleFlagZy() == 1) {
                errorMessage.add("该药品禁止住院患者使用。");
            }
        }
        return errorMessage;
    }


    /**
     * 删除草药模板
     * 管理员和有医嘱模板编辑，权限的可以直接删除
     * 科室主任有权限删除本科室的模板
     *
     * @param name     模板名称
     * @param deptCode 科室编码
     * @return 返回提示
     */
    public ResultVo<String> shanChuMuBan(String name, String deptCode) {
        YzOrderPatternCy mb = dao.caoYaoMuBanXiangQing(name);
        // 如果有这个权限直接删除
        if (publicServer.needRule(YiZhuPublicService.MU_BAN_BIAN_JI_QUAN_XIAN)) {
            // 本人创建的也可以直接删除
            if (mb.getCreateId().equals(TokenUtil.getInstance().getTokenUserId())) {
                return shanChuCaoYaoMuBan(name);
            }
            // 科主任 可以删除自己科室的模板
            if (publicServer.needRule(YiZhuPublicService.KE_ZHU_REN_BIAN_MA)) {
                if (mb.getDeptCode().trim().equals(deptCode)) {
                    return shanChuCaoYaoMuBan(name);
                }
            }
        } else {
            return shanChuCaoYaoMuBan(name);
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您没有权限删除。");
    }

    private ResultVo<String> shanChuCaoYaoMuBan(String name) {
        dao.shanChuMuBan(name);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<String> shanChuCaoYao(String patNo, Integer times, BigDecimal orderNo) {
        YzActOrderCy cy = dao.caoYaoXinXi(patNo, times, orderNo);
        if (cy == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有查询到原来的信息。");
        }
        log.info("删除草药==》操作人：{}", TokenUtil.getInstance().getTokenUserId());
        String message;
        if (CaoYaoEnumStatusFlag.收费.getFlag().equals(cy.getStatusFlag())) {
            dao.genXingCaoYaoShanChuBiaoZhi(patNo, times, orderNo, CaoYaoEnumStatusFlag.删除.getFlag());
            dao.shanChuYiZhu(orderNo);
            message = "无需申请退药成功。";
        } else {
            dao.genXingCaoYaoShanChuBiaoZhi(patNo, times, orderNo, CaoYaoEnumStatusFlag.申请退药.getFlag());
            message = "申请退药成功。";
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, message);
    }

}
