package thyyxxk.webserver.service.zhuyuanyiji;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.zhuyuanyiji.MedicineManagementDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.medicaltechnology.AsidePage;
import thyyxxk.webserver.entity.medicaltechnology.FetchMedicines;
import thyyxxk.webserver.entity.medicaltechnology.MedicinePage;
import thyyxxk.webserver.entity.medicaltechnology.PoisonousAnesthetics;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.utils.ListUtil;
import thyyxxk.webserver.utils.ResultVoUtil;
import thyyxxk.webserver.utils.TokenUtil;

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

@Slf4j
@Service
public class MedicineManagementService {
    private final MedicineManagementDao dao;
    private final PublicServer publicService;
    private final UserCache userCache;

    @Autowired
    public MedicineManagementService(MedicineManagementDao dao, PublicServer publicService, UserCache userCache) {
        this.dao = dao;
        this.publicService = publicService;
        this.userCache = userCache;
    }

    public ResultVo<List<MedicinePage>> fetchMedicinePages(FetchMedicines params) {
        transformDateToDatetime(params);
        List<MedicinePage> list = dao.selectMedicinePages(buildFetchPageNoQw(params));
        if (list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        return ResultVoUtil.success(list);
    }

    public ResultVo<List<MedicinePage>> fetchUsedMedicines(FetchMedicines params) {
        transformDateToDatetime(params);
        buildChildDepartments(params);
        List<MedicinePage> list = dao.selectUsedMedicines(params);
        if (list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        return ResultVoUtil.success(list);
    }

    public ResultVo<List<MedicinePage>> submitMedicinePages(FetchMedicines params) {
        if (ListUtil.isBlank(params.getChargeList())) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "请勾选需要提交的药品。");
        }
        transformDateToDatetime(params);
        Map<String, String> deptChargeCodes = new HashMap<>();
        for (MedicinePage page : params.getChargeList()) {
            String execUnit = page.getExecUnit();
            if (deptChargeCodes.containsKey(execUnit)) {
                String tempVal = deptChargeCodes.get(page.getExecUnit()) + ",'" + page.getChargeCode() + "'";
                deptChargeCodes.replace(execUnit, tempVal);
            } else {
                deptChargeCodes.put(execUnit, "'" + page.getChargeCode() + "'");
            }
        }
        for (Map.Entry<String, String> entry : deptChargeCodes.entrySet()) {
            params.setDept(entry.getKey());
            params.setChargeCodes(entry.getValue());
            int pageNo = publicService.getTheDrugListNo();
            dao.deleteExistTargetPageNo(pageNo);
            params.setPageNo(pageNo);
            dao.insertNewPageNo(params);
            dao.submitMedicinePages(params);
            log.info("【操作员：{}】提交药品单：{}", TokenUtil.getInstance().getTokenUserId(), params);
        }
        return ResultVoUtil.success(dao.selectMedicinePages(buildFetchPageNoQw(params)));
    }

    private QueryWrapper<?> buildFetchPageNoQw(FetchMedicines params) {
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.ge("charge_date", params.getStart())
                .le("charge_date", params.getEnd())
                .eq("isnull(a.page_no,0)", "0")
                .eq("isnull(confirm_flag,'0')", "0")
                .eq("a.group_no", "73")
                .apply(" a.charge_code=b.code and isnull(a.serial,'01')=b.serial")
                .in("exec_unit", publicService.getChildDeptByUserCode(false))
                .groupBy("b.code,b.serial having sum(a.amount)!=0");
        return qw;
    }

    public ResultVo<Map<String, Object>> fetchPoisonousAnesthetics(FetchMedicines params) {
        transformDateToDatetime(params);
        List<PoisonousAnesthetics> list = dao.selectPoisonousAnesthetics(params);
        if (list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        Map<String, List<PoisonousAnesthetics>> medicines = new TreeMap<>();
        for (PoisonousAnesthetics item : list) {
            String key = item.getChargeDate() + "^" + item.getChargeCode();
            if (medicines.containsKey(key)) {
                medicines.get(key).add(item);
            } else {
                List<PoisonousAnesthetics> temp = new ArrayList<>();
                temp.add(item);
                medicines.put(key, temp);
            }
        }
        Map<String, BigDecimal> amounts = new HashMap<>();
        for (Map.Entry<String, List<PoisonousAnesthetics>> entry : medicines.entrySet()) {
            BigDecimal sum = BigDecimal.ZERO;
            for (PoisonousAnesthetics item : entry.getValue()) {
                sum = sum.add(item.getChargeAmount());
            }
            amounts.put(entry.getKey(), sum);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("medicines", medicines);
        map.put("amounts", amounts);
        return ResultVoUtil.success(map);
    }

    public ResultVo<List<AsidePage>> fetchSubmittedPageNos(FetchMedicines params) {
        transformDateToDatetime(params);
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.ge("charge_date", params.getStart())
                .le("charge_date", params.getEnd())
                .gt("page_no", 0).eq("group_no", "73")
                .in("exec_unit", publicService.getChildDeptByUserCode(false))
                .groupBy("page_no,exec_unit");
        if (null != params.getPageNo()) {
            qw.eq("page_no", params.getPageNo());
        }
        List<AsidePage> list = dao.selectSubmittedPageNos(qw);
        if (list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        list.forEach(item -> item.setConfirmId(userCache.getEmployeeName(item.getConfirmId())));
        return ResultVoUtil.success(list);
    }

    public ResultVo<List<MedicinePage>> fetchMedicinePageDetail(AsidePage params) {
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.eq("a.page_no", params.getPageNo())
                .eq("a.group_no", "73")
                .eq("a.exec_unit", params.getExecUnit())
                .apply("a.charge_code=b.code and isnull(a.serial,'01')=b.serial")
                .groupBy("b.code,b.serial having sum(a.amount)!=0");
        return ResultVoUtil.success(dao.fetchMedicinePageDetail(qw));
    }

    private void transformDateToDatetime(FetchMedicines params) {
        params.setStart(params.getStart() + " 00:00:00.000");
        params.setEnd(params.getEnd() + " 23:59:59.999");
    }

    private void buildChildDepartments(FetchMedicines params) {
        String dept = params.getDept();
        List<String> children = dao.selectChildDepartments(dept);
        StringBuilder builder = new StringBuilder();
        builder.append("'").append(dept).append("'");
        for (String child : children) {
            builder.append(",'").append(child).append("'");
        }
        params.setDept(builder.toString());
    }
}
