package thyyxxk.webserver.service.inpatient.nursemodule;

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.dao.his.inpatient.nursemodule.PrintInfusionCardDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.inpatient.nursemodule.request.CardType;
import thyyxxk.webserver.entity.inpatient.nursemodule.request.InfusionInsert;
import thyyxxk.webserver.entity.inpatient.nursemodule.request.UpdatePrintStatus;
import thyyxxk.webserver.entity.inpatient.nursemodule.response.*;
import thyyxxk.webserver.entity.inpatient.nursemodule.request.QueryInfusionCard;
import thyyxxk.webserver.utils.DateUtil;
import thyyxxk.webserver.utils.ResultVoUtil;

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

@Slf4j
@Service
public class PrintInfusionCardService {
    private final PrintInfusionCardDao dao;

    @Autowired
    public PrintInfusionCardService(PrintInfusionCardDao dao) {
        this.dao = dao;
    }

    public ResultVo<List<PatientBed>> getPatientBeds(String wardCode) {
        return ResultVoUtil.success(dao.selectPatientBedList(wardCode));
    }

    public ResultVo<List<PatientInfusionInfo>> queryInfusionCardOrBottleCard(QueryInfusionCard params) {
        String bedNos = makeBedNos(params.getBedNos());
        InfusionInsert insert = getInfusionInsert(params, params.getWardCode(), bedNos);
        if (params.getCardType() == CardType.INFUSION_CARD) {
            return queryInfusionCard(insert);
        }
        return queryBottleCard(insert);
    }

    private ResultVo<List<PatientInfusionInfo>> queryInfusionCard(InfusionInsert insert) {
        String wardCode = insert.getWardCode();
        List<PatientBriefInfo> targetPatients = dao.selectTargetPatients(wardCode, insert.getBedNos());
        String prefix = "▲";

        dao.deleteOldInfusion(wardCode);
        dao.insertNewInfusion(insert);
        dao.insertInfusionAgain(wardCode);
        List<YzActOccInfusionNew> mainDrugs = dao.selectMainDrugs(wardCode);

        if (mainDrugs.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有当天的输液卡。");
        }

        List<YzActOccInfusionNew> sideDrugs = dao.selectSideDrugs(wardCode);
        Map<String, List<YzActOccInfusionNew>> sideDrugMap = new HashMap<>();
        sideDrugs.forEach(drug -> {
            drug.setDrugName(prefix + drug.getDrugName());
            String key = drug.getParentNo();
            if (sideDrugMap.containsKey(key)) {
                sideDrugMap.get(key).add(drug);
            } else {
                List<YzActOccInfusionNew> tempList = new ArrayList<>();
                tempList.add(drug);
                sideDrugMap.put(key, tempList);
            }
        });
        List<InfusionCard> list = new ArrayList<>();
        for (YzActOccInfusionNew item : mainDrugs) {
            InfusionCard card = new InfusionCard();
            card.setMainDrug(item);
            List<YzActOccInfusionNew> sideDrugList = sideDrugMap.get(item.getActOrderNo());
            if (null == sideDrugList) {
                list.add(card);
                continue;
            }
            card.setSideDrugs(sideDrugList);
            list.add(card);
        }

        Map<String, PatientInfusionInfo> tempMap = new HashMap<>();
        for (InfusionCard card : list) {
            String key = card.getMainDrug().getInpatientNo();
            if (tempMap.containsKey(key)) {
                tempMap.get(key).getDrugGroups().add(card);
            } else {
                PatientInfusionInfo infusionInfo = new PatientInfusionInfo();
                List<InfusionCard> tempList = new ArrayList<>();
                tempList.add(card);
                infusionInfo.setDrugGroups(tempList);
                tempMap.put(key, infusionInfo);
            }
        }
        List<PatientInfusionInfo> response = new ArrayList<>();
        targetPatients.forEach(target -> {
            PatientInfusionInfo infusionInfo = tempMap.get(target.getPatNo());
            if (null != infusionInfo) {
                target.setAgeLabel(DateUtil.calculateAgeLabelByDays(target.getAgeDays()));
                infusionInfo.setPatInfo(target);
                response.add(infusionInfo);
            }
        });
        return ResultVoUtil.success(response);
    }

    private ResultVo<List<PatientInfusionInfo>> queryBottleCard(InfusionInsert insert) {
        String wardCode = insert.getWardCode();
        List<PatientBriefInfo> targetPatients = dao.selectTargetPatients(wardCode, insert.getBedNos());
        Map<String, PatientBriefInfo> patInfoMap = new HashMap<>();
        for (PatientBriefInfo info : targetPatients) {
            info.setAgeLabel(DateUtil.calculateAgeLabelByDays(info.getAgeDays()));
            patInfoMap.put(info.getPatNo(), info);
        }
        dao.deleteOldInfusion(wardCode);
        dao.insertNewBottleCard(insert);
        List<YzActOccInfusionNew> mainDrugs = dao.selectMainDrugsForBottleCard(insert);
        List<YzActOccInfusionNew> sideDrugs = dao.selectSideDrugsForBottleCard(insert);

        List<PatientInfusionInfo> response = new ArrayList<>();
        for (YzActOccInfusionNew main : mainDrugs) {
            main.setStartHour(DateUtil.formatDatetime(main.getStartTime(), "HH:mm"));
            PatientInfusionInfo info = new PatientInfusionInfo();
            info.setPatInfo(patInfoMap.get(main.getInpatientNo()));
            info.setBottleCardDrugs(fetchDrugsForBottleCard(main, sideDrugs));
            response.add(info);
        }
        return ResultVoUtil.success(response);
    }

    private List<YzActOccInfusionNew> fetchDrugsForBottleCard(YzActOccInfusionNew main, List<YzActOccInfusionNew> sideDrugs) {
        List<YzActOccInfusionNew> list = new ArrayList<>();
        list.add(main);
        String prefix = "▲";
        for (YzActOccInfusionNew drug : sideDrugs) {
            if (drug.getParentNo().equals(main.getActOrderNo())) {
                drug.setDrugName(prefix + drug.getOrderName());
                drug.setStartHour(DateUtil.formatDatetime(drug.getStartTime(), "HH:mm"));
                list.add(drug);
            }
        }
        return list;
    }

    private InfusionInsert getInfusionInsert(QueryInfusionCard params, String wardCode, String bedNos) {
        InfusionInsert insert = new InfusionInsert();
        insert.setStartTime(params.getExecuteDate() + " 00:00:00.000");
        insert.setEndTime(params.getExecuteDate() + " 23:59:59.999");
        insert.setWardCode(wardCode);
        insert.setBedNos(bedNos);
        insert.setAlwaysFlag(params.getFrequency().getLabel());
        String printComment = params.getCardType() == CardType.INFUSION_CARD ?
                params.getPrintRange().getInfusionLabel() :
                params.getPrintRange().getBottleLabel();
        insert.setPrintComment(printComment);
        return insert;
    }

    private String makeBedNos(List<String> bedNos) {
        if (null == bedNos || bedNos.isEmpty()) {
            return "''";
        }
        List<String> temp = new ArrayList<>();
        StringBuilder sb = new StringBuilder();
        for (String bedNo : bedNos) {
            if (temp.contains(bedNo)) {
                continue;
            }
            temp.add(bedNo);
            sb.append(",'").append(bedNo).append("'");
        }
        return sb.substring(1);
    }

    public String updatePrintStatus(UpdatePrintStatus request) {
        if (null == request.getOrderNos() || request.getOrderNos().isEmpty()) {
            return "empty orderNos";
        }
        String status = request.getCardType() == CardType.INFUSION_CARD ? "S" : "J";
        StringBuilder sb = new StringBuilder();
        for (String orderNo : request.getOrderNos()) {
            sb.append(",'").append(orderNo).append("'");
        }
        String orderNos = sb.substring(1);
        dao.updateYzActOccPrintStatus(status, orderNos);
        return status;
    }
}
