package thyyxxk.webserver.service.dictionary;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.dao.his.dictionary.EmrDataMaintenanceDao;
import thyyxxk.webserver.dao.his.zhuyuanyisheng.emr.EmrPatientDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.zhuyuanyisheng.emr.EmrDataElement;
import thyyxxk.webserver.entity.zhuyuanyisheng.emr.EmrDataExtract;
import thyyxxk.webserver.entity.zhuyuanyisheng.emr.EmrDataMaintenance;
import thyyxxk.webserver.utils.*;

import java.util.*;

/**
 * @author 肖蟾
 */
@Service
@Slf4j
public class EmrDataMaintenanceServer {

    private final EmrDataMaintenanceDao dao;

    private final EmrPatientDao emrPatientDao;

    public EmrDataMaintenanceServer(EmrDataMaintenanceDao dao, EmrPatientDao emrPatientDao) {
        this.dao = dao;
        this.emrPatientDao = emrPatientDao;
    }

    private static String keyParameterSubstitution(String sqlSentence, String patNo, Integer times) {
        Map<String, String> map = new HashMap<>();
        map.put("PAT_NO", "'" + patNo + "'");
        map.put("TIMES", times.toString());
        return StringUtil.replaceElementValue(sqlSentence, map);
    }

    private static void createObject(Map<String, List<Map<String, Object>>> groupMap,
                                     String key,
                                     Object value,
                                     Map<String, Object> extraMap) {
        String[] keys = key.split("-");
        List<Map<String, Object>> groupChild = new ArrayList<>();
        Map<String, Object> childMap = new HashMap<>();
        // gy_麻醉方式-code
        // gy-麻醉方式-name
        String suffix = "名称";
        if (Objects.equals(keys[2], "code")) {
            suffix = "编码";
        }
        if (value instanceof String && StringUtil.isBlank((String) value)) {
            groupMap.put(keys[1] + suffix, null);
            return;
        }

        if (value == null) {
            groupMap.put(keys[1] + suffix, null);
            return;
        }

        extraMap.put(keys[1] + suffix, value);

        if (groupMap.containsKey(keys[1])) {
            childMap.putAll(groupMap.get(keys[1]).get(0));
            childMap.put(keys[2], value);
            groupChild.add(childMap);
            groupMap.replace(keys[1], groupChild);
        } else {
            childMap.put(keys[2], value);
            groupChild.add(childMap);
            groupMap.put(keys[1], groupChild);
        }
    }


    public ResultVo<Page<EmrDataMaintenance>> getElectronicMedicalRecordDataElementSql(int currentPage, int pageSize, long total) {
        Page<EmrDataMaintenance> page = new Page<>(currentPage, pageSize, total == 0);
        dao.getElectronicMedicalRecordDataElementSql(page);
        return ResultVoUtil.success(page);
    }

    public ResultVo<JSONObject> testSql(EmrDataMaintenance emr) {
        String sql = keyParameterSubstitution(emr.getSqlSentence(), emr.getPatNo(), emr.getTimes());
        if (emr.getDataType().equals(0)) {
            Map<String, Object> sqlData = dao.testSql(sql);
            if (null == sqlData || sqlData.isEmpty()) {
                return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "sql没问题，但是没得数据。");
            }
            fieldConversion(sqlData);
            if (StringUtil.notBlank(emr.getGroupName())) {
                String map = String.format("{\"%s\" : %s}", emr.getGroupName(), JSON.toJSONStringWithDateFormat(sqlData, DateUtil.DEFAULT_PATTERN));
                return ResultVoUtil.success(JSON.parseObject(map));
            }
            return ResultVoUtil.success(JSON.parseObject(JSON.toJSONStringWithDateFormat(sqlData, DateUtil.DEFAULT_PATTERN)));
        } else {
            List<Map<String, Object>> listMap = dao.testSqlList(sql);
            for (Map<String, Object> item : listMap) {
                fieldConversion(item);
            }
            if (ListUtil.isBlank(listMap)) {
                return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "sql没问题，但是没得数据。");
            }
            Map<String, List<Map<String, Object>>> formatData = new HashMap<>(1);
            formatData.put(emr.getGroupName(), listMap);
            return ResultVoUtil.success(JSON.parseObject(JSON.toJSONStringWithDateFormat(formatData, DateUtil.DEFAULT_PATTERN)));
        }
    }

    private static void fieldConversion(Map<String, Object> sqlData) {
        Map<String, List<Map<String, Object>>> groupingMap = new HashMap<>();
        Map<String, Object> extraMap = new HashMap<>();
        List<String> groupKeys = new ArrayList<>();
        for (Map.Entry<String, Object> dbitem : sqlData.entrySet()) {
            Object value = dbitem.getValue();
            String key = dbitem.getKey();
            if (value != null) {
                if (value instanceof String) {
                    sqlData.replace(key, ((String) value).trim());
                    if (key.startsWith("gy-")) {
                        groupKeys.add(key);
                        createObject(groupingMap, key, ((String) value).trim(), extraMap);
                    }
                }
            }
        }
        sqlData.putAll(groupingMap);
        sqlData.putAll(extraMap);
        for (String item : groupKeys) {
            sqlData.remove(item);
        }
    }


    public ResultVo<String> addData(EmrDataMaintenance emr) {
        String userCode = TokenUtil.getInstance().getTokenUserId();
        dao.addData(emr.getName(), emr.getSqlSentence(), userCode, emr.getDataType());
        log.info("新增电子病历维护 ==> 操作人:{},数据:{}", userCode, JSON.toJSONString(emr));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<String> deleteById(Integer id) {
        dao.deleteById(id, TokenUtil.getInstance().getTokenUserId());
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<String> updateData(EmrDataMaintenance emr) {
        if (emr == null || emr.getId() == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有查询到id");
        }
        dao.updateData(emr, TokenUtil.getInstance().getTokenUserId());
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    /**
     * 获取患者的数据元
     *
     * @param patNo 住院号
     * @param times 住院次数
     * @return 返回数据元
     * @throws Exception 错误
     */
    public ResultVo<JSONObject> getEmrInpatientData(String patNo, Integer times) throws Exception {
        List<EmrDataMaintenance> emrData = dao.getEmrInpatientData();
        JSONObject obj = new JSONObject();
        for (EmrDataMaintenance item : emrData) {
            item.setPatNo(patNo);
            item.setTimes(times);
            ResultVo<JSONObject> resultVo = testSql(item);
            if (Objects.equals(resultVo.getCode(), ExceptionEnum.SUCCESS.getCode())) {
                if (null != resultVo.getData()) {
                    obj.putAll(resultVo.getData());
                }
            }
        }

        EmrDataElement emrDataElement = emrPatientDao.obtainPatientSOriginalData(patNo, times);
        if (emrDataElement != null) {
            obj.putAll(JSONObject.parseObject(emrDataElement.getDataElement()));
        }
        return ResultVoUtil.success(obj);
    }


    public ResultVo<List<EmrDataExtract>> getExtractDataSource() {
        return ResultVoUtil.success(dao.getExtractDataSource());
    }

    public ResultVo<String> updateExtractDataSource(EmrDataExtract param) {
        dao.updateExtractDataSource(param);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<String> deleteExtractDataSource(String code) {
        dao.deleteExtractDataSource(code);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<String> insertExtractDataSource(EmrDataExtract param) {
        log.info("插入的数据：{}", JSON.toJSONString(param));
        try {
            dao.insertExtractDataSource(param);
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
        } catch (Exception e) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "编码不能重复。");
        }


    }


}
