package thyyxxk.webserver.service.zhuyuanyiji;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.models.auth.In;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.GetDateFormat;
import thyyxxk.webserver.dao.his.zhuyuanyiji.PatientFee;
import thyyxxk.webserver.dao.his.zhuyuanyiji.QueRenYiZhuShouFeiDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.datamodify.YzActOrder;
import thyyxxk.webserver.entity.inpatient.patient.Patient;
import thyyxxk.webserver.entity.zhuyuanyisheng.jianyanjiancha.YshYjReq;
import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.XinZhenYzActOrder;
import thyyxxk.webserver.entity.yiji.YzZyPatientFeeData;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.service.inpatient.PatientService;
import thyyxxk.webserver.service.zhuyuanyisheng.JianYanJianChaShenQingService;
import thyyxxk.webserver.service.zhuyuanyisheng.YiZhuLuRuServer;
import thyyxxk.webserver.utils.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 描述： 确认医嘱收费
 * </p>
 *
 * @author xc
 * @date 2021-09-27 11:50
 */
@Service
@Slf4j
public class QueRenYiZhuShouFeiServer {
    private final QueRenYiZhuShouFeiDao dao;
    private final JianYanJianChaShenQingService jianYanJianChaShenQingService;
    private final YiZhuLuRuServer yiZhuLuRuServer;
    private final PublicServer publicServer;
    private final PatientService patientService;

    public QueRenYiZhuShouFeiServer(QueRenYiZhuShouFeiDao dao, PublicServer server, PatientService patientService,JianYanJianChaShenQingService jianYanJianChaShenQingService,YiZhuLuRuServer yiZhuLuRuServer) {
        this.dao = dao;
        this.publicServer = server;
        this.patientService = patientService;
        this.jianYanJianChaShenQingService = jianYanJianChaShenQingService;
        this.yiZhuLuRuServer = yiZhuLuRuServer;

    }

    public QueRenYiZhuShouFeiServer getThis() {
        return SpringUtil.getBean(this.getClass());
    }

    /**
     * @param yzActOrder 查询条件 住院号，住院次数，执行科室， 分页
     * @return 返回分页数据
     */
    public ResultVo<IPage<YzActOrder>> getXuQueFeiYiZhu(YzActOrder yzActOrder) {
        IPage<YzActOrder> page = new Page<>(yzActOrder.getCurrentPage(), yzActOrder.getPageSize(), false);
        List<String> execUnitList = publicServer.getKeShiLieBiaoList(yzActOrder.getExecUnit());
        if (StringUtil.isBlank(yzActOrder.getExecUnit())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "科室信息为空 [・_・?]");
        }
        // 查看历史 等于 3 就是查看 没有被确认的 不等于 3 就是查看历史
        log.info("查询需确费医嘱：数据：{}", JSON.toJSONString(yzActOrder));
        String fenLei = "a.ward_code";
        if (yzActOrder.getFenLei() != null && yzActOrder.getFenLei().equals(1)) {
            fenLei = "(select count(*) from yz_zy_patient_fee " +
                     "where op_id = '" + TokenUtil.getInstance().getTokenUserId() + "' and inpatient_no = a.inpatient_no and admiss_times = a.admiss_times and charge_status <> 3) desc";
        }
        page.setTotal(dao.getXuQueFeiYiZhuTotal(yzActOrder.getInpatientNo(), yzActOrder.getWardCode(), execUnitList, yzActOrder.getStartTimeString(),
                yzActOrder.getEndTimeString()));
        dao.getXuQueFeiYiZhu(page, yzActOrder.getInpatientNo(), yzActOrder.getWardCode(), execUnitList, yzActOrder.getStartTimeString(), yzActOrder.getEndTimeString(),
                fenLei);
        if (page.getRecords().isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        List<YzActOrder> ziJieDian = dao.getXuQueFeiXiangXiXinXi(execUnitList, page.getRecords(), yzActOrder.getStartTimeString(), yzActOrder.getEndTimeString());
        Map<String, List<YzActOrder>> ziJieDianMap = ziJieDian.stream().collect(
                Collectors.groupingBy(item -> item.getInpatientNo() + item.getAdmissTimes())
        );
        for (int i = 0; i < page.getRecords().size(); i++) {
            YzActOrder yz = page.getRecords().get(i);
            String key = yz.getInpatientNo() + yz.getAdmissTimes();
            if (yz.getList() == null) {
                yz.setList(new ArrayList<>());
            }
            if (ziJieDianMap.containsKey(key)) {
                yz.getList().addAll(ziJieDianMap.get(key));
            }
        }
        return ResultVoUtil.success(page);
    }

    public ResultVo<List<YzActOrder>> huoQuLiShiQueFeiYiZhu(String startTime,
                                                            String endTime,
                                                            String inpatientNo,
                                                            String wardCode,
                                                            String execUnit,
                                                            Integer paiXu,
                                                            String code) {
        if (StringUtil.isBlank(startTime) || StringUtil.isBlank(endTime)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "开始时间和结束时间为空。");
        } else if (StringUtil.isBlank(execUnit)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "执行科室为空。");
        }
        List<YzActOrder> liShiShuJu = dao.huoQuLiShiXinXi(startTime, endTime, inpatientNo, publicServer.getKeShiLieBiaoList(execUnit), wardCode, code);
        if (ListUtil.notBlank(liShiShuJu)) {
            return ResultVoUtil.success(liShiShuJu);
        }
        log.info("开始时间：{}，结束时间：{}，住院号：{}，病房：{}，执行科室：{}，排序：{}", startTime, endTime, inpatientNo, wardCode, execUnit, paiXu);
        return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
    }

    /**
     * @param param 医嘱修改
     * @return 返回提示
     */
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> baoCunYiZhuQueFeiShuJu(YzActOrder param) {
        List<Patient> xuYaoFeiYongJieShou = new ArrayList<>();
        List<YzActOrder> xuYaoQueFei = new ArrayList<>();
        if (ListUtil.isBlank(param.getList())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请选择需要确费的数据 ヽ(ー_ー)ノ");
        }
        if (StringUtil.isBlank(param.getExecUnit())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "科室信息为空 ∑(っ°Д°;)っ卧槽，不见了");
        }
        for (YzActOrder yzActOrder : param.getList()) {
            if (yzActOrder.getList() != null && !yzActOrder.getList().isEmpty()) {
                for (YzActOrder actOrder : yzActOrder.getList()) {
                    if ("1".equals(actOrder.getChargeStatus())) {
                        xuYaoQueFei.add(actOrder);
                        Patient xuQueFei = new Patient();
                        xuQueFei.setInpatientNo(yzActOrder.getInpatientNo());
                        xuQueFei.setAdmissTimes(yzActOrder.getAdmissTimes());
                        xuQueFei.setName(yzActOrder.getName());
                        xuQueFei.setLedgerSn(yzActOrder.getLedgerSn());
                        if (!xuYaoFeiYongJieShou.contains(xuQueFei)) {
                            xuYaoFeiYongJieShou.add(xuQueFei);
                        }
                    } else if ("2".equals(actOrder.getChargeStatus())) {
                        xuYaoQueFei.add(actOrder);
                    }
                }
            }
        }
        if (xuYaoQueFei.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有进行确认操作请勿点击。 ψ(*｀ー´)ψ");
        } else {
            //  这个查询是否有重复操作的 sql 需要重新写
            List<YzActOrder> yiQueFei = dao.huoQuLiShiQueFeiXinXi(publicServer.getKeShiLieBiaoList(param.getExecUnit()), xuYaoFeiYongJieShou);
            Map<String, YzActOrder> yiQueFeiMap = yiQueFei.stream().collect(
                    Collectors.toMap(L -> L.getInpatientNo() + L.getAdmissTimes() + DateUtil.formatDatetime(L.getOccTime()) + L.getChargeCode() + L.getChargeFee() + L.getOrderCount() + L.getActOrderNo(), a -> a, (k1, k2) -> k2));
            for (YzActOrder yzActOrder : xuYaoQueFei) {
                String key = yzActOrder.getInpatientNo() + yzActOrder.getAdmissTimes() + DateUtil.formatDatetime(yzActOrder.getOccTime()) +
                             yzActOrder.getChargeCode() + yzActOrder.getChargeFee() + yzActOrder.getOrderCount() + yzActOrder.getActOrderNo();
                if (yiQueFeiMap.containsKey(key)) {
                    YzActOrder queRenTiShi = yiQueFeiMap.get(key);
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("存在已被确费的项目,请对该项目选择不操作或刷新数据重新加载。 !!!∑(ﾟДﾟノ)ノ <br>患者姓名：【%s】<br>项目：【%s】<br> 医嘱号：【%s】<br> 医嘱时间：【%s】<br>执行人：【%s】<br> 操作时间：【%s】", queRenTiShi.getPatientName(),
                            queRenTiShi.getOrderName(), queRenTiShi.getActOrderNo(), DateUtil.formatDatetime(queRenTiShi.getOccTime()), queRenTiShi.getOpIdName(), DateUtil.formatDatetime(queRenTiShi.getOpDate())));
                }
            }
        }
        dao.baoCunYiZhuQueFei(xuYaoQueFei, TokenUtil.getInstance().getTokenUserId());
        // 患者要去重
        Set<Patient> huanZhe = new HashSet<>();
        for (Patient patient : xuYaoFeiYongJieShou) {
            Patient pa = new Patient();
            pa.setInpatientNo(patient.getInpatientNo());
            pa.setAdmissTimes(patient.getAdmissTimes());
            pa.setLedgerSn(patient.getLedgerSn());
            huanZhe.add(pa);
        }
        getThis().acceptFees(huanZhe);
        log.info("医嘱确费保存==》操作人：{}，数据：{}", TokenUtil.getInstance().getTokenUserId(), JSON.toJSONStringWithDateFormat(xuYaoQueFei, GetDateFormat.DATE_TIME));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "操作成功。");
    }

    /**
     * @param reqNo 申请单号
     * @return 返回提示
     */
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<Object> orderYiZhuQueFeiShuJuOne(List<Integer> reqNo) {
        List<Patient> xuYaoFeiYongJieShou = new ArrayList<>();
        List<YzActOrder> xuYaoQueFei = new ArrayList<>();
//        if (ListUtil.isBlank(param.getList())) {
//            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请选择需要确费的数据 ヽ(ー_ー)ノ");
//        }
        List<YshYjReq> yshYjReqList = jianYanJianChaShenQingService.huoQuShengQingXiangQingDemo(reqNo);
        List<String> yjReqIdList = yshYjReqList.stream().map(e->String.valueOf(e.getActOrderNo())).collect(Collectors.toList());
        List<YzActOrder> yzActOrderList = dao.getXuQueFeiXiangXiByOrderList(new QueryWrapper<YzActOrder>().in("act_order_no", yjReqIdList));
        List<YzActOrder> yzActOrderFormatList = yzActOrderList.stream().map(e->{

            long timeInMillis = e.getOccTime().getTime();
            // 除以1000取整，再乘以1000，相当于去掉毫秒
            long truncatedTime = (timeInMillis / 1000) * 1000;
            e.setOccTime(new Date(truncatedTime));
            return e;
        }).collect(Collectors.toList());
                // 转换为 LocalDateTime

//        List<YzActOrder> yzActOrderList = yiZhuLuRuServer.getYiZhuShuJuByOrderNo(yjReqIdList);
        Integer ledgerSn = yiZhuLuRuServer.getledgerSnFromYiZhu(yshYjReqList.get(0).getInpatientNo(),yshYjReqList.get(0).getAdmissTimes());
//        return ResultVoUtil.success(yshYjReq);
        //变更为病人所属科室
        for (YzActOrder actOrder : yzActOrderFormatList) {
            if ("3".equals(actOrder.getChargeStatus())) {
                actOrder.setChargeStatus("1");
                actOrder.setActOrderNo(BigDecimal.valueOf(actOrder.getActOrderNo().intValue()));
                xuYaoQueFei.add(actOrder);
                Patient xuQueFei = new Patient();
                xuQueFei.setInpatientNo(actOrder.getInpatientNo());
                xuQueFei.setAdmissTimes(actOrder.getAdmissTimes());
                xuQueFei.setName(actOrder.getName());
                xuQueFei.setLedgerSn(ledgerSn);
                if (!xuYaoFeiYongJieShou.contains(xuQueFei)) {
                    xuYaoFeiYongJieShou.add(xuQueFei);
                }
            } else if ("2".equals(actOrder.getChargeStatus())) {
                xuYaoQueFei.add(actOrder);
            }
        }
        if (xuYaoQueFei.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有进行确认操作请勿点击。 ψ(*｀ー´)ψ");
        } else {
            //  这个查询是否有重复操作的 sql 需要重新写
            List<YzActOrder> yiQueFei = dao.huoQuLiShiQueFeiXinXi(publicServer.getKeShiLieBiaoList(yshYjReqList.get(0).getExecDept().replaceAll("\\s+$", "")), xuYaoFeiYongJieShou);
            Map<String, YzActOrder> yiQueFeiMap = yiQueFei.stream().collect(
                    Collectors.toMap(L -> L.getInpatientNo() + L.getAdmissTimes() + DateUtil.formatDatetime(L.getOccTime()) + L.getChargeCode() + L.getChargeFee() + L.getOrderCount() + L.getActOrderNo(), a -> a, (k1, k2) -> k2));
            for (YzActOrder yzActOrder : xuYaoQueFei) {
                String key = yzActOrder.getInpatientNo() + yzActOrder.getAdmissTimes() + DateUtil.formatDatetime(yzActOrder.getOccTime()) +
                        yzActOrder.getChargeCode() + yzActOrder.getChargeFee() + yzActOrder.getOrderCount() + yzActOrder.getActOrderNo();
                if (yiQueFeiMap.containsKey(key)) {
                    YzActOrder queRenTiShi = yiQueFeiMap.get(key);
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("存在已被确费的项目,请对该项目选择不操作或刷新数据重新加载。 !!!∑(ﾟДﾟノ)ノ <br>患者姓名：【%s】<br>项目：【%s】<br> 医嘱号：【%s】<br> 医嘱时间：【%s】<br>执行人：【%s】<br> 操作时间：【%s】", queRenTiShi.getPatientName(),
                            queRenTiShi.getOrderName(), queRenTiShi.getActOrderNo(), DateUtil.formatDatetime(queRenTiShi.getOccTime()), queRenTiShi.getOpIdName(), DateUtil.formatDatetime(queRenTiShi.getOpDate())));
                }
            }
        }
        dao.baoCunYiZhuQueFei(xuYaoQueFei, TokenUtil.getInstance().getTokenUserId());
        // 患者要去重
        Set<Patient> huanZhe = new HashSet<>();
        for (Patient patient : xuYaoFeiYongJieShou) {
            Patient pa = new Patient();
            pa.setInpatientNo(patient.getInpatientNo());
            pa.setAdmissTimes(patient.getAdmissTimes());
            pa.setLedgerSn(patient.getLedgerSn());
            huanZhe.add(pa);
        }
        getThis().acceptFees(huanZhe);
        log.info("医嘱确费保存==》操作人：{}，数据：{}", TokenUtil.getInstance().getTokenUserId(), JSON.toJSONStringWithDateFormat(xuYaoQueFei, GetDateFormat.DATE_TIME));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "操作成功 (๑*◡*๑)");
    }

    /**
     * 通过患者的住院号 确认费用
     *
     * @param huanZhe 患者信息
     */
    @Async
    public void acceptFees(Set<Patient> huanZhe) {
        for (Patient patient : huanZhe) {
            try {
                patientService.receiveAndRecalculateCost(patient);
            } catch (Exception ignored) {
            }
        }
    }

}
