package thyyxxk.webserver.service.surgicalmanagement;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.dao.his.surgicalmanagement.SurgeryArrangementDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.dictionary.CodeName;
import thyyxxk.webserver.entity.surgeryarrangement.QuerySurgeryParams;
import thyyxxk.webserver.entity.surgeryarrangement.request.StatisticsInquiry;
import thyyxxk.webserver.entity.surgeryarrangement.response.SurgeryStatistics;
import thyyxxk.webserver.entity.zhuyuanyisheng.shoushu.OpRecord;
import thyyxxk.webserver.service.hutoolcache.DeptCache;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.service.outpatient.wxapi.SendWxInfoService;
import thyyxxk.webserver.utils.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class SurgeryArrangementService {
    private final SurgeryArrangementDao dao;
    private final SendWxInfoService sendWxInfoService;
    private final UserCache userCache;
    private final DeptCache deptCache;
    private static final String[] OP_RECORD_COLUMNS = {"room_code", "op_datetime", "remark",
            "arrangement_executed", "urgent_clinic_flag", "preoperative_visit",
            "preoperative_preparation", "tw_flag", "sstc"};

    public SurgeryArrangementService(SurgeryArrangementDao dao, SendWxInfoService sendWxInfoService, UserCache userCache, DeptCache deptCache) {
        this.dao = dao;
        this.sendWxInfoService = sendWxInfoService;
        this.userCache = userCache;
        this.deptCache = deptCache;
    }

    public ResultVo<Map<String, List<CodeName>>> getDicList() {
        Map<String, List<CodeName>> map = new HashMap<>();
        map.put("allRooms", dao.selectSurgeryRooms());
        map.put("allWards", dao.getAllSurgicalWard());
        map.put("surStaffs", dao.selectStaffsByDeptCode("8001300"));
        map.put("aneStaffs", dao.selectStaffsByDeptCode("1000534"));
        return ResultVoUtil.success(map);
    }

    public ResultVo<List<OpRecord>> selectSurgeryArrangements(QuerySurgeryParams param) {
        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.ge("op_datetime", param.getStartTime());
        qw.le("op_datetime", param.getEndTime());
        if (param.getJzFlag()) {
            qw.eq("urgent_clinic_flag", "1");
        }
        if (!param.getStatus().equals("0")) {
            qw.eq("a.status", param.getStatus());
        }
        if (StringUtil.notBlank(param.getPatNo())) {
            qw.eq("a.inpatient_no", param.getPatNo());
        }
        if (StringUtil.notBlank(param.getWard())) {
            qw.eq("a.ward_code", param.getWard());
        }
        List<OpRecord> list = dao.selectSurgeryArrangements(qw);
        if (ListUtil.isBlank(list)) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        List<OpRecord> canceled = new ArrayList<>();
        list.forEach(item -> {
            item.setWardName(deptCache.getDeptName(item.getWardCode()));
            item.setDeptName(deptCache.getDeptName(item.getDeptCode()));
            item.setApplyDocName(userCache.getEmployeeName(item.getApplyDoc()));
            item.setDoctorZdName(userCache.getEmployeeName(item.getDoctorZd()));
            item.setDoctor1Name(userCache.getEmployeeName(item.getDoctor1()));
            item.setDoctor2Name(userCache.getEmployeeName(item.getDoctor2()));
            item.setNurseXhName(userCache.getEmployeeName(item.getNurseXh()));
            item.setNurseQxName(userCache.getEmployeeName(item.getNurseQx()));
            item.setDoctorMzYsName(userCache.getEmployeeName(item.getDoctorMzYs()));
            item.setDoctorMzHsName(userCache.getEmployeeName(item.getDoctorMzHs()));
            if (item.getStatus().equals("d")) {
                canceled.add(item);
            }
        });
        list.removeIf(item -> item.getStatus().equals("d"));
        list.addAll(canceled);
        return ResultVoUtil.success(list);
    }

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

    public ResultVo<String> updateSurgeryStatus(Integer recordId, String status) {
        if (hasArrangementPermission()) {
            dao.updateSurgeryStatus(recordId, status);
            return ResultVoUtil.success("操作成功。");
        }
        return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, "操作失败，您没有安排手术的权限。");
    }

    private boolean isOpRecordColumn(String targetColumn) {
        for (String column : OP_RECORD_COLUMNS) {
            if (column.equals(targetColumn)) {
                return true;
            }
        }
        return false;
    }

    public ResultVo<String> updateArrangement(Integer recordId, String column, String value) {
        if (hasArrangementPermission()) {
            String table = isOpRecordColumn(column) ? "op_record" : "op_record_join";
            if (value.isEmpty()) {
                value = null;
            }
            dao.updateArrangement(table, column, value, recordId);
            return ResultVoUtil.success();
        }
        return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, "操作失败，您没有安排手术的权限。");
    }

    private boolean hasArrangementPermission() {
        if (TokenUtil.getInstance().getTokenUserId().equals("01897")) {
            return true;
        }
        Integer count = dao.selectArrangementPermission(TokenUtil.getInstance().getTokenUserId());
        return null != count && count > 0;
    }

    public ResultVo<String> notifyDoctor(OpRecord record) {
        List<String> codeRsList = dao.selectCodeRsList(record.getDoctorZd(), record.getApplyDoc(),
                record.getDoctorMzYs(),record.getDoctor1(),record.getDoctor2(),record.getNurseXh(),
                record.getNurseQx());
        if (codeRsList.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有查询到手术医生和申请医生的工号。");
        }
        StringBuilder sb = new StringBuilder();
        for (String codeRs : codeRsList) {
            sb.append("|").append(codeRs);
        }
        String touser = sb.substring(1);
        String roomName = dao.selectRoomName(record.getRoomCode());
        String content = String.format("[%s]申请的住院号[%s]病人姓名[%s]由[%s]主刀的[%s]已安排在[%s][%s]",
                record.getApplyDocName(),record.getInpatientNo(),record.getPatientName(),
                record.getDoctorZdName(),record.getOpName(),
                DateUtil.formatDatetime(record.getOpDatetime()),roomName);
        JSONObject response = sendWxInfoService.sendCorpWxMsg(touser, content);
        if (null == response) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer errcode = response.getInteger("errcode");
        if (null == errcode) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        if (errcode == 0) {
            return ResultVoUtil.success("推送成功。");
        }
        String message = "推送失败。" + response.getString("errmsg");
        return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, message);
    }

    public SurgeryStatistics queryStatistics(StatisticsInquiry inquiry) {
        List<OpRecord> opRecordList = dao.selectOpRecordStatistics(inquiry.getStartDate(), inquiry.getEndDate());
        if (opRecordList.isEmpty()) {
            return null;
        }

        SurgeryStatistics response = new SurgeryStatistics();
        response.setTotal(opRecordList.size());
        Map<String, List<OpRecord>> map = new HashMap<>();

        for (OpRecord record : opRecordList) {
            String key = getKey(inquiry, record);
            if (StringUtil.isBlank(key)) {
                continue;
            }
            if (map.containsKey(key)) {
                map.get(key).add(record);
            } else {
                List<OpRecord> tempList = new ArrayList<>();
                tempList.add(record);
                map.put(key, tempList);
            }
        }
        response.setSurgeryMap(map);
        return response;
    }

    private static String getKey(StatisticsInquiry inquiry, OpRecord record) {
        switch (inquiry.getStatisticsLabel()) {
            case BY_SURGERY:
                return record.getOpName();
            case BY_LEVEL:
                return record.getOpScaleName();
            case BY_DEPARTMENT:
            default:
                return record.getDeptName();
        }
    }
}
