package thyyxxk.webserver.service.inpatient;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.Capacity;
import thyyxxk.webserver.constants.GetDateFormat;
import thyyxxk.webserver.dao.his.inpatient.TransferInOfExpensesDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.datamodify.GetDropdownBox;
import thyyxxk.webserver.entity.datamodify.MzChargeDetail;
import thyyxxk.webserver.entity.datamodify.ZyDetailCharge;
import thyyxxk.webserver.entity.inpatient.ZyActpatient;
import thyyxxk.webserver.entity.medicalinsurance.inpatient.ZyPatientInfo;
import thyyxxk.webserver.entity.transferInOfExpenses.data.CorrectInvoice;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.utils.*;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 描述： 门急诊费用转入
 * </p>
 *
 * @author xc
 * @date 2021-05-25 17:35
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class TransferInOfExpensesService {

    private final TransferInOfExpensesDao dao;
    private final PublicServer publicServer;
    private final RestTemplateUtils template;
    private final UserCache userCache;

    @Value("${thmz-api-url}")
    private String thmzApiUrl;


    /**
     * 查询再远患者信息
     *
     * @param inpatientNo 住院号
     * @return 返回一个信息
     */
    public ResultVo<ZyActpatient> queryHuanZhe(String inpatientNo) {
        log.info("查询患者信息-->住院号：{}", inpatientNo);
        ZyActpatient pojo = dao.queryHuanZhe(inpatientNo);
        if (pojo != null) {
            return ResultVoUtil.success(pojo);
        }
        return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "没有找到该患者可能已出院，╮(╯▽╰)╭");
    }

    /**
     * 通过机制号来查找信息
     *
     * @param serialNo 机制号
     * @return 返回信息
     */
    public ResultVo<List<MzChargeDetail>> getSerialNo(Integer serialNo) {
        List<MzChargeDetail> list = dao.getSerialNo("mz_charge_detail", "mz_receipt_serial", serialNo);
        if (!list.isEmpty()) {
            return ResultVoUtil.success(list);
        } else {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
    }

    /**
     * 查看患者是通过门急诊转入的费用项目
     *
     * @param inpatientNo 住院号
     * @param currentPage 当前页
     * @param pageSize    页数
     * @return 返回项目
     */
    public ResultVo<Map<String, Object>> getZyJiMenZhenZhuangRuFeiYong(String inpatientNo, String chargeCodeMX, String admissTimes, long currentPage, long pageSize) {
        Integer ledgerSn = publicServer.getLedgerSn(inpatientNo, Integer.valueOf(admissTimes));
        IPage<ZyDetailCharge> page = new Page<>(currentPage, pageSize);
        // 因为我这里用的是分页 所以才会这样
        List<ZyDetailCharge> list = dao.getZyJiMenZhenZhuangRuFeiYong(page, inpatientNo, chargeCodeMX, admissTimes, ledgerSn);
        List<ZyDetailCharge> sumList = dao.sumZyFee(inpatientNo, chargeCodeMX, admissTimes, ledgerSn);
        Map<String, Object> map = new HashMap<>(Capacity.TWO);
        if (page.getTotal() > 0 || !list.isEmpty()) {
            BigDecimal sum = new BigDecimal(0);
            for (ZyDetailCharge zyDetailCharge : sumList) {
                sum = sum.add(zyDetailCharge.getChargeFee().multiply(zyDetailCharge.getChargeAmount()));
            }
            map.put("data", list);
            map.put("total", page.getTotal());
            map.put("sum", sum);
            return ResultVoUtil.success(map);
        }
        return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
    }

    /**
     * 删除病人通过急门诊转入的费用 数据
     *
     * @param param 删除的条件
     * @return 返回是否成功
     */
    public ResultVo<String> shanChuFeiYong(ZyDetailCharge param) {
        log.info("删除该患者通过急门诊转入的费用 --> 操作员：{}， 通过主键来删除数据：{}", TokenUtil.getInstance().getTokenUserId(), JSON.toJSONStringWithDateFormat(param, GetDateFormat.DATE_TIME));
        dao.shanChuFeiYong(param);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "删除成功 ୧(๑•̀◡•́๑)૭");
    }

    /**
     * 插入 通过急门诊转入的费用
     *
     * @param param 要插入的数据
     * @return 返回通知
     */
    public ResultVo<String> baoCunHuanZheZhuYuanFeiYong(ZyActpatient param) {
        if (param.getSerialNo() == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "刷新页面机制号为空");
        }
        param.setStaffId(TokenUtil.getInstance().getTokenUserId());
        List<MzChargeDetail> list = param.getList();
        //查询流水号
        Integer maxDetailSn = dao.getMaxDetailSn(param.getInpatientNo(), param.getAdmissTimes());
        ZyPatientInfo patInfo = dao.getPatientHospitalStay(param.getInpatientNo());
        if (patInfo == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有找到患者信息");
        }
        if (DateUtil.shiJianDaXiao(param.getChargeDate(), patInfo.getAdmissDate(), "<")) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "费用发生时间不能小于入院时间。");
        }

        if (patInfo.getDisDate() != null) {
            if (DateUtil.shiJianDaXiao(param.getChargeDate(), patInfo.getDisDate(), ">")) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "费用发生时间不能大于出院时间，患者出院时间为:" + DateUtil.formatDatetime(param.getDisDate()));
            }
        }
        // 流水号取出这个患者流水值的最大值 在加 1
        // 同时计算 出患者的总金额 以及 费用的类型
        list.removeIf(item -> "BILL99".equals(item.getChargeCodeMx()));
        for (MzChargeDetail mzChargeDetail : list) {
            if (mzChargeDetail.getChargeFee().compareTo(BigDecimal.ZERO) == 0) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "录入费用不得为 0");
            }
            mzChargeDetail.setDetailSn(maxDetailSn += 1);
        }
        dao.insertInfoZyDetailCharge(param, list);
        log.info("急门诊费用插入 --> 操作人：{} ， 数据：{}", param.getStaffId(), JSON.toJSONStringWithDateFormat(param, GetDateFormat.DATE_TIME));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "操作成功。");
    }


    public ResultVo<String> correctInvoice(CorrectInvoice.CorrectInvoiceReq param) {
        CorrectInvoice correctInvoice = dao.getSerialNoByInvoiceNo(param.getSerialNo());
        if (correctInvoice == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有找到该发票号");
        }

        String url = thmzApiUrl + "/uploadPartMzInvoice";
        correctInvoice.setOpId(TokenUtil.getInstance().getTokenUserId());
        param.getCodes().replaceAll(String::trim);
        correctInvoice.setChargeItemCodes(param.getCodes());

        ResultVo<String> resultVo = template.post(url, correctInvoice, String.class, "门诊部分开票");
        if (resultVo == null) {
            return R.fail(ExceptionEnum.LOGICAL_ERROR, "调用接口错误，请联系管理员。");
        }
        if (resultVo.getCode().equals(0)) {
            return R.ok(resultVo.getData());
        }
        return R.fail(ExceptionEnum.LOGICAL_ERROR, resultVo.getMessage());
    }

    /**
     * 获取发票的二维码
     *
     * @param serialNo 机制号
     * @return 数据
     */
    public ResultVo<CorrectInvoice.DzcfVo> getDzfpQrcodeBySerialNo(Integer serialNo) {
        CorrectInvoice correctInvoice = dao.getSerialNoByInvoiceNo(serialNo);
        return getDzfpQrcodeByCorrectInvoice(correctInvoice, serialNo);
    }

    public ResultVo<CorrectInvoice.DzcfVo> getDzfpQrcodeByCorrectInvoice(CorrectInvoice correctInvoice, Integer serialNo) {
        if (correctInvoice == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有找到该发票号");
        }
        // 查询是否已经冲正了，如果冲正了就直接用冲正的东西
        CorrectInvoice.DzcfVo uploadData = dao.getMzDzcfUpload(correctInvoice);

        if (uploadData == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有找到电子发票");
        }
        List<String> changeCodes = StrUtil.isNotBlank(uploadData.getChargeCode()) ? Arrays.asList(uploadData.getChargeCode().split(",")) : null;

        QueryWrapper<?> qw = new QueryWrapper<>();
        qw.eq("patient_id", correctInvoice.getPatientId())
                .eq("times", correctInvoice.getTimes())
                .eq("receipt_no", correctInvoice.getReceiptNo())
                .eq("serial_no", serialNo)
                .in("charge_item_code", changeCodes);

        BigDecimal dzfpChangeTotal = dao.getDzfpChangeTotal(qw);
        uploadData.setPatientId(correctInvoice.getPatientId());

        if (dzfpChangeTotal != null) {
            uploadData.setTotal(dzfpChangeTotal.toPlainString());
        } else {
            uploadData.setTotal("0");
        }
        uploadData.setOpName(userCache.getEmployeeName(correctInvoice.getOpId()));
        uploadData.setPrintDate(DateUtil.format(new Date(), DatePattern.CHINESE_DATE_FORMAT));
        return R.ok(uploadData);

    }


    /**
     * 远程搜索 项目名称
     *
     * @param pyCode 拼音码 大写的
     * @return 返回多个项目的名称
     */
    public ResultVo<List<GetDropdownBox>> queryEntryName(String pyCode) {
        return ResultVoUtil.success(dao.queryEntryName("%" + pyCode.toUpperCase() + "%"));
    }

}
