package thyyxxk.webserver.service.inpatient.casefrontsheet.tcm;

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.BizException;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.dao.his.inpatient.casefrontsheet.CaseFrontSheetDao;
import thyyxxk.webserver.dao.his.inpatient.casefrontsheet.tcmsheet.TcmFrontSheetDisdiagDao;
import thyyxxk.webserver.dao.his.inpatient.casefrontsheet.tcmsheet.TcmFrontSheetMainDao;
import thyyxxk.webserver.dao.his.inpatient.casefrontsheet.tcmsheet.TcmFrontSheetSurgeryDao;
import thyyxxk.webserver.entity.casefrontsheet.request.SheetOverview;
import thyyxxk.webserver.entity.casefrontsheet.state.State;
import thyyxxk.webserver.entity.casefrontsheet.tcmsheet.TcmFrontSheetDisdiag;
import thyyxxk.webserver.entity.casefrontsheet.tcmsheet.TcmFrontSheetIcuinfo;
import thyyxxk.webserver.entity.casefrontsheet.tcmsheet.TcmFrontSheetMain;
import thyyxxk.webserver.entity.casefrontsheet.tcmsheet.TcmFrontSheetSurgery;
import thyyxxk.webserver.entity.dictionary.CodeName;
import thyyxxk.webserver.service.hutoolcache.DeptCache;
import thyyxxk.webserver.utils.*;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class TcmSheetMainService {
    private final CaseFrontSheetDao wstSheetDao;
    private final TcmFrontSheetMainDao tcmSheetDao;
    private final TcmFrontSheetDisdiagDao diagDao;
    private final TcmFrontSheetSurgeryDao surgeryDao;
    private final DeptCache deptCache;

    @Autowired
    public TcmSheetMainService(CaseFrontSheetDao wstSheetDao, TcmFrontSheetMainDao tcmSheetDao, TcmFrontSheetDisdiagDao diagDao, TcmFrontSheetSurgeryDao surgeryDao, DeptCache deptCache) {
        this.wstSheetDao = wstSheetDao;
        this.tcmSheetDao = tcmSheetDao;
        this.diagDao = diagDao;
        this.surgeryDao = surgeryDao;
        this.deptCache = deptCache;
    }

    public TcmFrontSheetMain getSheetInfo(SheetOverview ov) {
        QueryWrapper<TcmFrontSheetMain> wrapper = new QueryWrapper<>();
        wrapper.eq("pat_no", ov.getPatNo());
        wrapper.eq("times", ov.getTimes());
        TcmFrontSheetMain sheet = tcmSheetDao.selectOne(wrapper);

        Date admdate = tcmSheetDao.getAdmDate("zy_actpatient", ov.getPatNo(), ov.getTimes());
        if (null == admdate) {
            admdate = tcmSheetDao.getAdmDate("zy_inactpatient", ov.getPatNo(), ov.getTimes());
        }

        if (null != sheet) {
            sheet.setDisdiagList(getSheetDisDiags(sheet.getId(), ov));
            sheet.setSurgeryList(getSheetSurgeries(sheet.getId(), ov));
            sheet.setIcuInfoList(getSheetIcuinfos(sheet.getId(), ov));
            if (null == sheet.getDismissDay()) {
                Date disdate = wstSheetDao.getDismissDateFromYzActOrder("yz_act_order", ov.getPatNo(), ov.getTimes());
                if (null == disdate) {
                    disdate = wstSheetDao.getDismissDateFromYzActOrder("yz_inact_order", ov.getPatNo(), ov.getTimes());
                }
                fillDisdate(sheet, admdate, disdate);
            }
            return sheet;
        }
        int inHospital = ov.getInOutFlag();
        if (inHospital == State.InHospital.NO) {
            if (wstSheetDao.selectActCount(ov.getPatNo(), ov.getTimes()) > 0) {
                inHospital = State.InHospital.YES;
            }
        }
        sheet = tcmSheetDao.getAPatientMi(ov.getPatNo());
        if (null == sheet) {
            throw new BizException(ExceptionEnum.NO_DATA_EXIST);
        }
        Date birthday = tcmSheetDao.getBirthday(ov.getPatNo());
        if (null != birthday) {
            sheet.setAge(DateUtil.calculateAge(birthday, admdate));
            String[] birthdayArr = DateUtil.formatDate(birthday).split("-");
            sheet.setBirthYear(Integer.parseInt(birthdayArr[0]));
            sheet.setBirthMonth(Integer.parseInt(birthdayArr[1]));
            sheet.setBirthDay(Integer.parseInt(birthdayArr[2]));
        }

        TcmFrontSheetMain sheet1 = inHospital == State.InHospital.YES ?
                tcmSheetDao.getZyActPatient("zy_actpatient", ov.getPatNo(), ov.getTimes()) :
                tcmSheetDao.getZyActPatient("zy_inactpatient", ov.getPatNo(), ov.getTimes());
        if (null == sheet1) {
            sheet1 = inHospital == State.InHospital.YES ?
                    tcmSheetDao.getZyActPatient("zy_inactpatient", ov.getPatNo(), ov.getTimes()) :
                    tcmSheetDao.getZyActPatient("zy_actpatient", ov.getPatNo(), ov.getTimes());
        }

        if (null != sheet.getAge() && sheet.getAge() == 0) {
            sheet.setInfAge(DateUtil.calculateNewBornAge(birthday, admdate));
        }

        if (null == sheet1.getDismissDay()) {
            final Date disdate = inHospital == State.InHospital.YES ?
                    wstSheetDao.getDismissDateFromYzActOrder("yz_inact_order", ov.getPatNo(), ov.getTimes())
                    : wstSheetDao.getDismissDateFromYzActOrder("yz_act_order", ov.getPatNo(), ov.getTimes());
            fillDisdate(sheet, admdate, disdate);
        }
        TcmFrontSheetMain sheet2 = tcmSheetDao.getBatjBa1(ov.getPatNo(), ov.getTimes());
        if (sheet2 == null && wstSheetDao.isBatjBa1Exist(ov.getPatNo(), ov.getTimes()) == 0) {
            wstSheetDao.createBatjBa1(ov.getPatNo(), ov.getTimes(), sheet.getName(), admdate, sheet1.getAdmissDept(), sheet1.getAdmissWard());
            log.info("tcm insert batjBa1>>> " + ov.getPatNo() + ", " + ov.getTimes());
        }
        TcmFrontSheetMain sheet3 = inHospital == 1 ?
                tcmSheetDao.getBatjBa2("zy_actpatient", ov.getPatNo(), ov.getTimes()) :
                tcmSheetDao.getBatjBa2("zy_inactpatient", ov.getPatNo(), ov.getTimes());
        Date zkrq = tcmSheetDao.getZkrq(ov.getPatNo(), ov.getTimes());
        if (null != zkrq) {
            String[] zkrqArr = DateUtil.formatDate(zkrq).split("-");
            sheet1.setQltyCtrlYear(Integer.parseInt(zkrqArr[0]));
            sheet1.setQltyCtrlMonth(Integer.parseInt(zkrqArr[1]));
            sheet1.setQltyCtrlDay(Integer.parseInt(zkrqArr[2]));
        }
        if (sheet3 == null && wstSheetDao.isBatjBa2Exist(ov.getPatNo(), ov.getTimes()) == 0) {
            wstSheetDao.createBatjBa2(ov.getPatNo(), ov.getTimes());
            log.info("tcm insert batjBa2>>> " + ov.getPatNo() + ", " + ov.getTimes());
        }
        FrontSheetUtil.mergeObject(sheet1, sheet);
        FrontSheetUtil.mergeObject(sheet2, sheet);
        FrontSheetUtil.mergeObject(sheet3, sheet);

        if (null == sheet.getAdmissYear()) {
            String admdateStr = DateUtil.formatDatetime(admdate, "yyyy-MM-dd-HH-mm-ss");
            String[] admdateArr = admdateStr.split("-");
            sheet.setAdmissYear(Integer.parseInt(admdateArr[0]));
            sheet.setAdmissMonth(Integer.parseInt(admdateArr[1]));
            sheet.setAdmissDay(Integer.parseInt(admdateArr[2]));
            sheet.setAdmissHour(Integer.parseInt(admdateArr[3]));
        }

        sheet.setAdmissDeptName(deptCache.getDeptName(sheet.getAdmissDept()));
        sheet.setAdmissWardName(deptCache.getDeptName(sheet.getAdmissWard()));
        sheet.setTransDeptName(deptCache.getDeptName(sheet.getTransDept()));
        sheet.setDismissDeptName(deptCache.getDeptName(sheet.getDismissDept()));
        sheet.setDismissWardName(deptCache.getDeptName(sheet.getDismissWard()));

        sheet.setDisdiagList(getSheetDisDiags(null, ov));
        sheet.setSurgeryList(getSheetSurgeries(null, ov));
        sheet.setIcuInfoList(getSheetIcuinfos(null, ov));
        List<CodeName> patCharges = tcmSheetDao.selectPatCharges(ov.getPatNo(), ov.getTimes());
        for (CodeName item : patCharges) {
            String fst = String.valueOf(item.getCode().charAt(0)).toUpperCase();
            String code = fst + item.getCode().substring(1);
            try {
                Method m = sheet.getClass().getMethod("set" + code, String.class);
                m.invoke(sheet, item.getName());
            } catch (Exception e) {
                log.error("反射出错", e);
            }
        }
        sheet.setSszlFee(DecimalUtil.add(sheet.getAnesthetizeFee(), sheet.getSurgeryFee()));
        return sheet;
    }

    private void fillDisdate(TcmFrontSheetMain sheet, Date admdate, Date disdate) {
        if (null != disdate) {
            int days = DateUtil.daysBetween(disdate, admdate);
            sheet.setInHospDays(0 == days ? 1 : days);
            String disdateStr = DateUtil.formatDatetime(disdate, "yyyy-MM-dd-HH-mm-ss");
            String[] disdateArr = disdateStr.split("-");
            sheet.setDismissYear(Integer.parseInt(disdateArr[0]));
            sheet.setDismissMonth(Integer.parseInt(disdateArr[1]));
            sheet.setDismissDay(Integer.parseInt(disdateArr[2]));
            sheet.setDismissHour(Integer.parseInt(disdateArr[3]));
        }
    }

    private List<TcmFrontSheetDisdiag> getSheetDisDiags(String sheetId, SheetOverview ov) {
        List<TcmFrontSheetDisdiag> disdiags = null != sheetId ?
                tcmSheetDao.selectSignedSheetDiags(sheetId) :
                tcmSheetDao.getDisdiags(ov.getPatNo(), ov.getTimes());
        while (disdiags.size() < 6) {
            disdiags.add(new TcmFrontSheetDisdiag());
        }
        return disdiags;
    }

    private List<TcmFrontSheetSurgery> getSheetSurgeries(String sheetId, SheetOverview ov) {
        List<TcmFrontSheetSurgery> surgeries = null != sheetId ?
                tcmSheetDao.selectSignedSheetSurgeries(sheetId) :
                tcmSheetDao.getSurgeries(ov.getPatNo(), ov.getTimes());
        while (surgeries.size() < 7) {
            surgeries.add(new TcmFrontSheetSurgery());
        }
        return surgeries;
    }

    private List<TcmFrontSheetIcuinfo> getSheetIcuinfos(String sheetId, SheetOverview ov) {
        List<TcmFrontSheetIcuinfo> icuinfos = new ArrayList<>();
        while (icuinfos.size() < 3) {
            icuinfos.add(new TcmFrontSheetIcuinfo());
        }
        return icuinfos;
    }

    public String saveTcmSheet(TcmFrontSheetMain sheet) {
        if (StringUtil.isBlank(sheet.getId())) {
            sheet.setId(SnowFlakeId.instance().nextId());
            tcmSheetDao.insert(sheet);
        } else {
            tcmSheetDao.updateById(sheet);
        }
        dealDisdiags(sheet);
        dealSurgeries(sheet);
        return sheet.getId();
    }

    private void dealDisdiags(TcmFrontSheetMain sheet) {
        List<TcmFrontSheetDisdiag> rawDiagList = sheet.getDisdiagList();
        List<TcmFrontSheetDisdiag> tmpDiagList = new ArrayList<>();
        for (int i = 0; i < rawDiagList.size(); i++) {
            TcmFrontSheetDisdiag diag = rawDiagList.get(i);
            if (StringUtil.isBlank(diag.getTcmCode()) && StringUtil.isBlank(diag.getWstCode())) {
                break;
            }
            diag.setId(SnowFlakeId.instance().nextId());
            diag.setSheetId(sheet.getId());
            tmpDiagList.add(diag);
        }
        diagDao.delOldDiag(sheet.getId());
        if (!tmpDiagList.isEmpty()) {
            diagDao.insert(tmpDiagList);
        }
    }

    private void dealSurgeries(TcmFrontSheetMain sheet) {
        List<TcmFrontSheetSurgery> rawSurgeries = sheet.getSurgeryList();
        List<TcmFrontSheetSurgery> tmpSurgeries = new ArrayList<>();
        for (int i = 0; i < rawSurgeries.size(); i++) {
            TcmFrontSheetSurgery surgery = rawSurgeries.get(i);
            if (StringUtil.isBlank(surgery.getCode())) {
                break;
            }
            surgery.setId(SnowFlakeId.instance().nextId());
            surgery.setSheetId(sheet.getId());
            tmpSurgeries.add(surgery);
        }
        surgeryDao.delOldSurgery(sheet.getId());
        if (!tmpSurgeries.isEmpty()) {
            surgeryDao.insert(tmpSurgeries);
        }
    }
}
