package thyyxxk.webserver.service.inpatient.adverseevent;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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.Capacity;
import thyyxxk.webserver.dao.his.inpatient.adverseevent.AdverseEventDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.adverseevent.*;
import thyyxxk.webserver.entity.dictionary.CodeName;
import thyyxxk.webserver.service.hutoolcache.DeptCache;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.utils.*;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @author dj
 */
@Slf4j
@Service
public class AdverseEventService {
    private final AdverseEventDao dao;
    private final DeptCache deptCache;
    private final UserCache userCache;

    @Autowired
    public AdverseEventService(AdverseEventDao dao, DeptCache deptCache, UserCache userCache) {
        this.dao = dao;
        this.deptCache = deptCache;
        this.userCache = userCache;
    }

    public ResultVo<String> submitNewReport(ReportDetail reportDetail) {
        reportDetail.setNurseReason(arrToStr(reportDetail.getNurseReasonArr()));
        reportDetail.setPatientReason(arrToStr(reportDetail.getPatientReasonArr()));
        reportDetail.setEnvironReason(arrToStr(reportDetail.getEnvironReasonArr()));
        reportDetail.setManageReason(arrToStr(reportDetail.getManageReasonArr()));
        reportDetail.setProNurse(arrToStr(reportDetail.getProNurseArr()));
        reportDetail.setProPatient(arrToStr(reportDetail.getProPatientArr()));
        reportDetail.setProEnviron(arrToStr(reportDetail.getProEnvironArr()));
        reportDetail.setProManage(arrToStr(reportDetail.getProManageArr()));
        reportDetail.setDepartment(deptCache.getDeptName(reportDetail.getDeptCode()));
        if (reportDetail.getModify()) {
            dao.modifyReport(reportDetail);
        } else {
            String userCode = TokenUtil.getInstance().getTokenUserId();
            String codeRs = dao.selectCodeRsByCode(userCode);
            reportDetail.setUserId(codeRs);
            reportDetail.setTid(String.valueOf(System.currentTimeMillis()));
            reportDetail.setSubmitDatetime(new Date());
            dao.submitNewReport(reportDetail);
        }
        return ResultVoUtil.success();
    }

    public ResultVo<List<ReportIndex>> getHistories() {
        String codeRs = dao.selectCodeRsByCode(TokenUtil.getInstance().getTokenUserId());
        return ResultVoUtil.success(dao.getHistories(codeRs));
    }

    public ResultVo<ReportDetail> getReportDetail(Integer pid, String level) {
        return ResultVoUtil.success(getReport(pid));
    }

    public ResultVo<List<ReportIndex>> getReportsForDept() {
        List<String> codes = dao.getLeaderDepts(TokenUtil.getInstance().getTokenUserId());
        return ResultVoUtil.success(dao.getReportsForDeptLeader(codes));
    }

    public ResultVo<String> updateDeptHandled(HandlerInfo indata) {
        CodeName userCodeName = dao.selectUserCodeRsAndName(TokenUtil.getInstance().getTokenUserId());
        indata.setUserId(userCodeName.getCode());
        indata.setUserName(userCodeName.getName());
        indata.setDatetime(new Date());
        dao.updateDeptHandled(indata);
        return ResultVoUtil.success();
    }

    public ResultVo<List<CodeName>> getAllDepts() {
        return ResultVoUtil.success(dao.getAllDepts());
    }

    public ResultVo<String> updateDeleted(Integer pid) {
        dao.updateDeleted(pid, TokenUtil.getInstance().getTokenUserId());
        return ResultVoUtil.success();
    }

    public ResultVo<Map<String, Object>> getAllReports(QueryParam param) {
        IPage<ReportIndex> iPage = new Page<>(param.getCurrentPage(), param.getPageSize());
        String statement = makeQueryStatement(param);
        iPage = dao.getAllReports(iPage, param.getStart(), param.getEnd(), param.getWardCode(), statement);
        Map<String, Object> map = new HashMap<>(Capacity.TWO);
        map.put("list", iPage.getRecords());
        map.put("totalSize", iPage.getTotal());
        return ResultVoUtil.success(map);
    }

    public void exportExcel(HttpServletResponse response, QueryParam param) {
        IPage<ReportIndex> iPage = new Page<>(1, -1);
        String statement = makeQueryStatement(param);
        iPage = dao.getAllReports(iPage, param.getStart(), param.getEnd(), param.getWardCode(), statement);
        List<ReportIndex> list = iPage.getRecords();
        String[] title = {"报告id", "发生时间", "事件类型", "提交时间", "提交人", "科室", "处理状态", "处理人", "打印状态"};
        String[][] content = new String[list.size()][];
        for (int i = 0; i < list.size(); i++) {
            content[i] = new String[title.length];
            ReportIndex index = list.get(i);
            content[i][0] = String.valueOf(index.getPid());
            content[i][1] = DateUtil.formatDatetime(index.getOccurDatetime());
            content[i][2] = index.getCategory();
            content[i][3] = DateUtil.formatDatetime(index.getSubmitDatetime());
            content[i][4] = index.getUserName();
            content[i][5] = index.getDepartment();
            content[i][6] = index.getHandled() == 1 ? "已处理" : "未处理";
            content[i][7] = index.getDeptDealerName();
            content[i][8] = index.getPrinted() == 1 ? "已打印" : "未打印";
        }
        ExcelUtil.exportExcel(response, title, content);
    }

    private String makeQueryStatement(QueryParam param) {
        String statement = "";
        if (param.getType() == 1) {
            statement = " and category not like '医疗%' ";
        } else if (param.getType() == 2) {
            statement = " and category like '医疗%' ";
        }
        if (null != param.getLevel()) {
            statement += " and event_level='" + param.getLevel() + "'";
        }
        return statement;
    }

    public ResultVo<ReportDetail> updateFinalHandled(HandlerInfo indata) {
        CodeName userCodeName = dao.selectUserCodeRsAndName(TokenUtil.getInstance().getTokenUserId());
        indata.setUserId(userCodeName.getCode());
        indata.setUserName(userCodeName.getName());
        indata.setDatetime(new Date());
        dao.updateFinalHandled(indata);
        return ResultVoUtil.success(getReport(indata.getPid()));
    }

    public ResultVo<String> updatePrinted(Integer pid) {
        dao.updatePrinted(pid);
        return ResultVoUtil.success();
    }

    public ResultVo<String> updateFeedback(HandlerInfo body) {
        if (ListUtil.isBlank(body.getFeedbackList())) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "反馈选项不能为空！");
        }
        body.setFeedback(arrToStr(body.getFeedbackList()));
        String userid = TokenUtil.getInstance().getTokenUserId();
        String userName = userCache.get(userid).getName();
        body.setUserId(userid);
        body.setUserName(userName);
        dao.updateFeedback(body);
        return ResultVoUtil.success();
    }

    private ReportDetail getReport(Integer pid) {
        ReportDetail report = dao.getReportDetail(pid);
        report.setNurseReasonArr(strToArr(report.getNurseReason()));
        report.setPatientReasonArr(strToArr(report.getPatientReason()));
        report.setEnvironReasonArr(strToArr(report.getEnvironReason()));
        report.setManageReasonArr(strToArr(report.getManageReason()));
        report.setProNurseArr(strToArr(report.getProNurse()));
        report.setProPatientArr(strToArr(report.getProPatient()));
        report.setProEnvironArr(strToArr(report.getProEnviron()));
        report.setProManageArr(strToArr(report.getProManage()));
        report.setFeedbackList(strToArr(report.getFeedback()));
        return report;
    }

    private String arrToStr(List<String> ori) {
        StringBuilder temp = new StringBuilder();
        for (String str : ori) {
            temp.append(str).append("^");
        }
        return temp.toString();
    }

    private List<String> strToArr(String ori) {
        List<String> arr = new ArrayList<>();
        if (ori != null) {
            String[] strings = ori.split("\\^");
            for (String item : strings) {
                if ((item != null) && (!item.isEmpty())) {
                    arr.add(item);
                }
            }
        }
        return arr;
    }

    public List<AdverseDept> getAllAdverseDept() {
        return dao.getAllAdverseDept();
    }

    public String saveAdverseDept(AdverseDept adverseDept) {
        if (adverseDept.getEditType().equals("ADD")) {
            dao.insertAdverseDept(adverseDept);
        } else if (adverseDept.getEditType().equals("UPDATE")) {
            dao.updateAdverseDept(adverseDept);
        } else {
            dao.deleteAdverseDept(adverseDept);
        }
        return "操作成功";
    }
}
