package thyyxxk.webserver.service.mzmedical;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import thyyxxk.webserver.config.exception.BizException;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.dao.his.mzmedical.MzMedicalMainDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.executeItem.NumberEnum;
import thyyxxk.webserver.entity.mzmedical.MzMedicalField;
import thyyxxk.webserver.entity.mzmedical.MzMedicalMain;
import thyyxxk.webserver.entity.mzmedical.MzMedicalMainParam;
import thyyxxk.webserver.utils.AssertUtil;
import thyyxxk.webserver.utils.ResultVoUtil;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Description:门诊诊疗信息页
 * @Author:lihong
 * @Date: 2025/4/14
 */
@Service
@Slf4j
public class MzMedicalMainService {
    @Resource
    private MzMedicalMainDao dao;

    private final static String HOSPITAL_NAME = "沭阳铭和医院";
    private final static String SOCIAL_CREDIT_CODE = "430000150806";

    public List<MzMedicalField> queryMzMedicalField() {
        List<MzMedicalField> mzMedicalFields = dao.selectAllMzMedicalField();
        for (MzMedicalField item : mzMedicalFields) {
            item.setMedicalCode(StrUtil.toCamelCase(item.getMedicalCode()));
        }
        return mzMedicalFields;
    }


    public int updateDelFlag(MzMedicalMain mzMedicalMain) {
        AssertUtil.isnotBlank(mzMedicalMain.getPatientId(), "门诊号不能为空!");
        AssertUtil.isnotBlank(mzMedicalMain.getTimes(), "就诊次数不能为空!");
        AssertUtil.isnotBlank(mzMedicalMain.getDelFlag(), "删除标识不能为空!");
        return dao.updateDelFlag(mzMedicalMain);
    }

    public ResultVo queryMzMedicalMainPage(MzMedicalMainParam param) {
        AssertUtil.isnotBlank(param.getYearMoth(), "请选择月份");
        setStartAndEndTime(param);
        IPage page = new Page(param.getCurrentPage(), param.getPageSize());
        List list = dao.selectMzMedicalMainPage(page, param);
        if (list.size() > 0) {
            Map<String, Object> res = new HashMap<>(10);
            res.put("data", list);
            res.put("total", page.getTotal());
            return ResultVoUtil.success(res);
        }
        return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
    }

    private void setStartAndEndTime(MzMedicalMainParam param) {
        int lastDayOfMonth = DateUtil.getLastDayOfMonth(DateUtil.parseDate(param.getYearMoth() + "-01"));
        param.setStartTime(param.getYearMoth() + "-01 00:00:00");
        param.setEndTime(param.getYearMoth() + "-" + lastDayOfMonth + " 23:59:59");
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> generateMzMedicalMainByMoth(MzMedicalMainParam param) {
        AssertUtil.isnotBlank(param.getYearMoth(), "请选择月份");
        setStartAndEndTime(param);
        Integer count = dao.selectCount(param.getStartTime(), param.getEndTime());
        if (count != null) {
            if (Convert.toInt(param.getOverFlag(), 0) == 0) {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "已经有" + param.getYearMoth() + "月份数据了,不要重复生成!");
            }
            dao.delByVistDate(param.getStartTime(), param.getEndTime());
        }
        List<MzMedicalMain> mzMedicalMainSourceData = dao.selectMzMedicalSourceData(param.getStartTime(), param.getEndTime());
        AssertUtil.isnotBlank(mzMedicalMainSourceData, "没有需要生成的数据");
        List<MzMedicalMain> oprtSource = dao.selectOprtSource(param.getStartTime(), param.getEndTime());
        Map<String, List<MzMedicalMain>> oprtMap = null;
        if (CollUtil.isNotEmpty(oprtSource)) {
            oprtMap = oprtSource.stream().collect(Collectors.groupingBy(item -> joinPatientIdAndTimes(item.getPatientId(), item.getTimes())));
        }
        List<MzMedicalMain> gmyData = dao.selectAllergenInfo();
        Map<String, List<MzMedicalMain>> gmyMap = null;
        if (CollUtil.isNotEmpty(gmyData)) {
            gmyMap = gmyData.stream().collect(Collectors.groupingBy(MzMedicalMain::getPatientId));
        }
        for (MzMedicalMain mzMedicalMain : mzMedicalMainSourceData) {
            BeanUtil.trimStrFields(mzMedicalMain);
            mzMedicalMain.setHospitalName(HOSPITAL_NAME);
            mzMedicalMain.setSocialCreditCode(SOCIAL_CREDIT_CODE);
            mzMedicalMain.setCertificateType(getCertificateType(mzMedicalMain.getCertificateType()));
            mzMedicalMain.setGms(NumberEnum.ONE.getCode());
            mzMedicalMain.setQtgms(NumberEnum.ONE.getCode());
            mzMedicalMain.setGhDate(DateUtil.offsetSecond(mzMedicalMain.getVisitDate(), -(60 * 2 + RandomUtil.randomInt(0, 40) * 60)));
            mzMedicalMain.setFee25(BigDecimal.ZERO);
            if (!NumberEnum.ONE.getCode().equals(mzMedicalMain.getVisitType())) {
                if (mzMedicalMain.getDeptCode().contains("急诊")) {
                    mzMedicalMain.setVisitType(NumberEnum.ONE.getCode());
                }
            }
            if (CollUtil.isNotEmpty(gmyMap)) {
                List<MzMedicalMain> gmYw = gmyMap.get(mzMedicalMain.getPatientId());
                if (CollUtil.isNotEmpty(gmYw)) {
                    Set<String> gmCollect = gmYw.stream().map(MzMedicalMain::getAllergenName).collect(Collectors.toSet());
                    mzMedicalMain.setGms(NumberEnum.TWO.getCode());
                    mzMedicalMain.setAllergenName(CollUtil.join(gmCollect, "，"));
                }
            }
            if (StrUtil.isNotBlank(mzMedicalMain.getIcdCodeNew())) {
                String[] icdArr = mzMedicalMain.getIcdCodeNew().split(",");
                for (int i = 0; i < icdArr.length; i++) {
                    String icdCode = "icdCode" + (i == 0 ? "" : i);
                    ReflectUtil.setFieldValue(mzMedicalMain, icdCode, icdArr[i]);
                }
            }
            if (StrUtil.isNotBlank(mzMedicalMain.getIcdTextNew())) {
                String[] icdArr = mzMedicalMain.getIcdTextNew().split(",");
                for (int i = 0; i < icdArr.length; i++) {
                    String icdName = "icdName" + (i == 0 ? "" : i);
                    ReflectUtil.setFieldValue(mzMedicalMain, icdName, icdArr[i]);
                }
            }
            if (CollUtil.isNotEmpty(oprtMap) && CollUtil.isNotEmpty(oprtMap.get(joinPatientIdAndTimes(mzMedicalMain.getPatientId(), mzMedicalMain.getTimes())))) {
                List<MzMedicalMain> oprList = oprtMap.get(joinPatientIdAndTimes(mzMedicalMain.getPatientId(), mzMedicalMain.getTimes()));
                for (int i = 0; i < oprList.size(); i++) {
                    ReflectUtil.setFieldValue(mzMedicalMain, "oprDate" + (i + 1), oprList.get(i).getOprDate1());
                    ReflectUtil.setFieldValue(mzMedicalMain, "oprName" + (i + 1), oprList.get(i).getOprName1());
                    ReflectUtil.setFieldValue(mzMedicalMain, "oprCode" + (i + 1), oprList.get(i).getOprCode1());
                    ReflectUtil.setFieldValue(mzMedicalMain, "oprDoctor" + (i + 1), oprList.get(i).getOprDoctor1());
                    ReflectUtil.setFieldValue(mzMedicalMain, "mzfs" + (i + 1), oprList.get(i).getMzfs1());
                    ReflectUtil.setFieldValue(mzMedicalMain, "mzDoctor" + (i + 1), oprList.get(i).getMzDoctor1());
                    ReflectUtil.setFieldValue(mzMedicalMain, "oprScale" + (i + 1), oprList.get(i).getOprScale1());
                }
            }
            BigDecimal totalFee = BigDecimal.ZERO;
            for (int i = 1; i <= 24; i++) {
                if (i == 9) {
                    totalFee = totalFee.add(Convert.toBigDecimal(ReflectUtil.getFieldValue(mzMedicalMain, "fee901"), BigDecimal.ZERO));
                    totalFee = totalFee.add(Convert.toBigDecimal(ReflectUtil.getFieldValue(mzMedicalMain, "fee902"), BigDecimal.ZERO));
                } else if (i == 10) {
                    totalFee = totalFee.add(Convert.toBigDecimal(ReflectUtil.getFieldValue(mzMedicalMain, "fee1001"), BigDecimal.ZERO));
                    totalFee = totalFee.add(Convert.toBigDecimal(ReflectUtil.getFieldValue(mzMedicalMain, "fee1002"), BigDecimal.ZERO));
                    totalFee = totalFee.add(Convert.toBigDecimal(ReflectUtil.getFieldValue(mzMedicalMain, "fee1003"), BigDecimal.ZERO));

                } else {
                    totalFee = totalFee.add(Convert.toBigDecimal(ReflectUtil.getFieldValue(mzMedicalMain, "fee" + i), BigDecimal.ZERO));
                }
            }
            mzMedicalMain.setFee901(mzMedicalMain.getFee901().add(mzMedicalMain.getFee902()));
            mzMedicalMain.setFee1001(mzMedicalMain.getFee1001().add(mzMedicalMain.getFee1002()).add(mzMedicalMain.getFee1003()));
            mzMedicalMain.setTotalFee(totalFee);
        }
        List<List<MzMedicalMain>> split = CollUtil.split(mzMedicalMainSourceData, 15);
        for (List<MzMedicalMain> temp : split) {
            dao.batchInsertData(temp);
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "生成数据成功");
    }

    private String getCertificateType(String certificateType) {
        String str = "9";
        if ("1".equals(certificateType) || "01".equals(certificateType)) {
            return "1";
        } else if ("02".equals(certificateType)) {
            return "2";
        } else if ("03".equals(certificateType)) {
            return "3";
        } else if ("04".equals(certificateType) || "05".equals(certificateType)) {
            return "4";
        } else if ("08".equals(certificateType)) {
            return "6";
        } else if ("07".equals(certificateType)) {
            return "7";
        }
        return str;
    }

    private String joinPatientIdAndTimes(String patientId, Integer times) {
        return patientId + "_" + times;
    }

    public Map<String, List<Map<String, Object>>> queryMzMedicalZd() {
        List<Map<String, Object>> list = dao.selectMzMedicalZd();
        Map<String, List<Map<String, Object>>> typeCodeMap = list.stream().collect(Collectors.groupingBy(item -> (String) item.get("type_code")));
        return typeCodeMap;
    }


}
