package thyyxxk.webserver.service.reports;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.sidicts.MedType;
import thyyxxk.webserver.dao.his.reports.IllegalChargesAnalysisDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.datamodify.YzActOrder;
import thyyxxk.webserver.entity.dictionary.CodeName;
import thyyxxk.webserver.entity.reports.illegalchargesanalysis.IllegalChargeData;
import thyyxxk.webserver.entity.reports.illegalchargesanalysis.IllegalChargeTemplate;
import thyyxxk.webserver.entity.reports.illegalchargesanalysis.SearchChargeItem;
import thyyxxk.webserver.service.hutoolcache.DeptCache;
import thyyxxk.webserver.service.hutoolcache.RegionCache;
import thyyxxk.webserver.utils.ListUtil;
import thyyxxk.webserver.utils.ResultVoUtil;
import thyyxxk.webserver.utils.StringUtil;
import thyyxxk.webserver.utils.TokenUtil;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description: 违规收费项目分析实现类
 * @author: DingJie
 * @create: 2021-04-15 16:47:34
 **/
@Slf4j
@Service
public class IllegalChargesAnalysisService {
    private final IllegalChargesAnalysisDao dao;
    private static final String DASH = "_";
    private static final String ADMIN = "admin";
    private static final String ADMIN_2 = "admin_2";
    private final RegionCache regionCache;
    private final DeptCache deptCache;

    @Autowired
    public IllegalChargesAnalysisService(IllegalChargesAnalysisDao dao, RegionCache regionCache, DeptCache deptCache) {
        this.dao = dao;
        this.regionCache = regionCache;
        this.deptCache = deptCache;
    }

    public ResultVo<List<IllegalChargeTemplate>> fetchMyTemplates() {
        String code = TokenUtil.getInstance().getTokenUserId() + "%";
        List<IllegalChargeTemplate> tempList = dao.selectMyTemplates(code);
        List<IllegalChargeTemplate> resultList = new ArrayList<>();
        Map<String, IllegalChargeTemplate> treeMap = new HashMap<>(tempList.size());
        for (IllegalChargeTemplate item : tempList) {
            item.analyzeValue();
            treeMap.put(item.getId(), item);
            if (null == item.getParent()) {
                resultList.add(item);
            }
        }
        for (IllegalChargeTemplate item : tempList) {
            IllegalChargeTemplate template = treeMap.get(item.getParent());
            if (null != template) {
                if (null == template.getChildren()) {
                    template.setChildren(new ArrayList<>());
                }
                template.getChildren().add(item);
            }
        }
        return ResultVoUtil.success(resultList);
    }

    public ResultVo<String> insertNewTemplate(IllegalChargeTemplate template) {
        if (StringUtil.isBlank(template.getLabel())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "模板名称不能为空！");
        }
        if (template.getPersonal() == 0) {
            dao.insertNewTemplate(template);
            return ResultVoUtil.success("创建成功。");
        }
        StringBuilder id = new StringBuilder(template.getId());
        if (!id.toString().contains(DASH)) {
            template.setId(TokenUtil.getInstance().getTokenUserId() + DASH + id);
        } else {
            if (id.toString().startsWith(ADMIN)) {
                id = new StringBuilder(id.toString().replace(ADMIN, TokenUtil.getInstance().getTokenUserId()));
                template.setId(id.toString());
            }
        }
        if (template.getParent().startsWith(ADMIN) && !template.getParent().equals(ADMIN_2)) {
            template.setParent(template.getParent().replace("admin", TokenUtil.getInstance().getTokenUserId()));
        }
        id = new StringBuilder(template.getId());
        String[] idArr = id.toString().split("-");
        String lastBit = idArr[idArr.length - 1];
        int position = Integer.parseInt(lastBit);
        Integer exist = dao.selectCurrentId(id.toString());
        while (exist != null) {
            position++;
            idArr[idArr.length - 1] = String.valueOf(position);
            id = new StringBuilder();
            for (int i = 0; i < idArr.length - 1; i++) {
                id.append(idArr[i]).append("-");
            }
            id.append(position);
            exist = dao.selectCurrentId(id.toString());
        }
        template.setId(id.toString());
        dao.insertNewTemplate(template);
        log.info("创建模板：{}", template);
        return ResultVoUtil.success("创建成功。");
    }

    public ResultVo<String> deleteTemplate(IllegalChargeTemplate template) {
        String id = template.getId() + "%";
        dao.deleteTemplate(id);
        return ResultVoUtil.success("删除成功。");
    }

    public ResultVo<List<CodeName>> searchChargeItem(SearchChargeItem param) {
        String content = "%" + param.getContent().toUpperCase() + "%";
        String method;
        switch (param.getMethod()) {
            case "alpha":
                method = "py_code";
                break;
            case "code":
                method = "code";
                break;
            default:
                method = "name";
                break;
        }
        String include = param.getIncludeDeactivate() ? "like '%%'" : "!=1";
        return ResultVoUtil.success(dao.selectChargeItem(method, content, include));
    }

    public ResultVo<String> saveTemplateChanges(IllegalChargeTemplate template) {
        if (template.getType() == 0) {
            dao.updateTemplate(template);
            return ResultVoUtil.success();
        }
        if (null == template.getMainCharges() || template.getMainCharges().isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "收费主体不能为空！");
        }
        StringBuilder value = genTemplateValue(template.getMainCharges()).append("$");
        if (template.getAttribute() == 1) {
            if (null == template.getConflictCharges() || template.getConflictCharges().isEmpty()) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "冲突收费不能为空！");
            }
            value.append(genTemplateValue(template.getConflictCharges()));
        } else {
            if (null == template.getMaxChargeNum()) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "超量收费上限不能为空！");
            }
            value.append(template.getMaxChargeNum()).append("|").append(template.getMaxChargeUnit());
        }
        template.setValue(value.toString());
        dao.updateTemplate(template);
        return ResultVoUtil.success();
    }

    private StringBuilder genTemplateValue(List<CodeName> charges) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < charges.size(); i++) {
            CodeName charge = charges.get(i);
            builder.append(charge.getCode()).append("|").append(charge.getName());
            if (i < charges.size() - 1) {
                builder.append("#");
            }
        }
        return builder;
    }

    public ResultVo<List<IllegalChargeData>> analyzeTargetData(IllegalChargeTemplate template) {
        template.setStart(template.getStart() + " 00:00:00");
        template.setEnd(template.getEnd() + " 23:59:59");
        log.info("违规收费分析：{}", template);
        if (template.getAttribute() == 1) {
            return sameTimeCharge(template);
        }
        return overLimitCharge(template);
    }

    private ResultVo<List<IllegalChargeData>> sameTimeCharge(IllegalChargeTemplate template) {
        List<IllegalChargeData> resultList = new ArrayList<>();
        for (CodeName main : template.getMainCharges()) {
            List<IllegalChargeData> mainList = dao.selectChargeDataForSameTime(template.getStart(),
                    template.getEnd(), main.getCode());
            if (ListUtil.notBlank(template.getMedtypes())) {
                mainList.removeIf(item -> !template.getMedtypes().contains(item.getMedtype()));
            }
            for (IllegalChargeData item : mainList) {
                item.setInsuplcAdmdvsName(regionCache.get(item.getInsuplcAdmdvs()));
            }
            for (CodeName cflct : template.getConflictCharges()) {
                List<IllegalChargeData> cflctList = dao.selectChargeDataForSameTime(template.getStart(),
                        template.getEnd(), cflct.getCode());
                if (ListUtil.notBlank(template.getMedtypes())) {
                    cflctList.removeIf(item -> !template.getMedtypes().contains(item.getMedtype()));
                }
                List<Map<String, IllegalChargeData>> mapList = new ArrayList<>();
                Map<String, IllegalChargeData> map = new HashMap<>(mainList.size());
                mapList.add(map);
                for (IllegalChargeData item : mainList) {
                    String key = item.getInpatientNo() + "_" + item.getChargeDay();
                    if (map.containsKey(key)) {
                        Map<String, IllegalChargeData> tempMap = new HashMap<>();
                        tempMap.put(key, item);
                        mapList.add(tempMap);
                    } else {
                        map.put(key, item);
                    }
                }
                for (Map<String, IllegalChargeData> temp : mapList) {
                    for (IllegalChargeData item : cflctList) {
                        String key = item.getInpatientNo() + "_" + item.getChargeDay();
                        if (temp.containsKey(key)) {
                            IllegalChargeData originData = temp.get(key);
                            String ref = JSON.toJSONString(originData);
                            IllegalChargeData data = JSON.parseObject(ref, IllegalChargeData.class);
                            if (item.getAlreadyUsed() && originData.getAlreadyUsed()) {
                                continue;
                            }
                            data.setExecUnit(deptCache.getDeptName(data.getExecUnit()));
                            data.setDeptName(deptCache.getDeptName(data.getDeptName()));
                            data.setWardName(deptCache.getDeptName(data.getWardName()));
                            data.setMedtypeName(MedType.getName(item.getMedtype()));
                            data.setConflictChargeCode(item.getChargeCode());
                            data.setConflictChargeAmount(item.getChargeAmount());
                            data.setConflictChargeDate(item.getChargeDate());
                            data.setConflictChargeFee(item.getChargeFee());
                            data.setConflictChargeName(item.getChargeName());
                            data.setConflictDetailSn(item.getDetailSn());
                            data.setConflictOrderNo(item.getOrderNo());
                            data.setConflictExecUnit(deptCache.getDeptName(item.getExecUnit()));
                            item.setAlreadyUsed(true);
                            originData.setAlreadyUsed(true);
                            resultList.add(data);
                        }
                    }
                }
            }
        }
        return ResultVoUtil.success(resultList);
    }

    private ResultVo<List<IllegalChargeData>> overLimitCharge(IllegalChargeTemplate template) {
        List<IllegalChargeData> resultList = new ArrayList<>();
        for (CodeName main : template.getMainCharges()) {
            resultList.addAll(dao.selectChargeDataForOverLimit(template.getStart(), template.getEnd(),
                    main.getCode(), template.getMaxChargeNum()));
        }
        if (resultList.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        return ResultVoUtil.success(resultList);
    }

    public ResultVo<List<YzActOrder>> selectOrderPair(BigDecimal orderNo, BigDecimal conflictOrderNo) {
        List<YzActOrder> list = dao.selectYzActOrder(orderNo, conflictOrderNo);
        if (list.isEmpty()) {
            list = dao.selectYzInActOrder(orderNo, conflictOrderNo);
        }
        if (list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        if (list.size() == 1 || list.get(0).getActOrderNo().equals(orderNo)) {
            return ResultVoUtil.success(list);
        }
        List<YzActOrder> tmp = new ArrayList<>();
        tmp.add(list.get(1));
        tmp.add(list.get(0));
        return ResultVoUtil.success(tmp);
    }

    public ResultVo<List<IllegalChargeData>> queryHuanZheLiangCiRuYuanRiQi(IllegalChargeTemplate param) {
        List<IllegalChargeData> list = dao.queryHuanZheLiangCiRuYuanRiQi(param.getStart(), param.getEnd(), param.getMedtypes());
        if (list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        return ResultVoUtil.success(list);
    }

    public ResultVo<List<IllegalChargeData>> chaXunHuanZheZhuYuanJianGe(String startTime, String endTime, Integer tianShu) {
        return ResultVoUtil.success(dao.zhuYuanTianShu(startTime, endTime, tianShu));
    }
}


