package cn.hnthyy.thmz.service.impl.his.zy;

import cn.hnthyy.thmz.Utils.DateUtil;
import cn.hnthyy.thmz.entity.MzException;
import cn.hnthyy.thmz.entity.his.mz.Employee;
import cn.hnthyy.thmz.entity.his.zd.ZdChequeType;
import cn.hnthyy.thmz.entity.his.zy.ZyActpatient;
import cn.hnthyy.thmz.enums.GenderEnum;
import cn.hnthyy.thmz.enums.ResponceTypeEnum;
import cn.hnthyy.thmz.mapper.his.mz.EmployeeMapper;
import cn.hnthyy.thmz.mapper.his.zd.ZdChequeTypeMapper;
import cn.hnthyy.thmz.mapper.his.zy.ZyDailySettlementMapper;
import cn.hnthyy.thmz.service.his.zd.ZdUnitCodeService;
import cn.hnthyy.thmz.service.his.zy.ZyDailySettlementService;
import cn.hnthyy.thmz.vo.ZyDailySettlementVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ZyDailySettlementServiceImpl implements ZyDailySettlementService {
    @SuppressWarnings("all")
    @Autowired
    private ZyDailySettlementMapper zyDailySettlementMapper;
    @SuppressWarnings("all")
    @Autowired
    private ZdChequeTypeMapper zdChequeTypeMapper;
    @SuppressWarnings("all")
    @Autowired
    private EmployeeMapper employeeMapper;
    @Autowired
    private ZdUnitCodeService zdUnitCodeService;

    @Override
    public ZyDailySettlementVo getZyDailySettlementVo(String opId) throws MzException {
        if (StringUtils.isBlank(opId)) {
            throw new MzException("用户Id为空");
        }
        ZyDailySettlementVo zyDailySettlementVo = new ZyDailySettlementVo();
        Date now = new Date();
        Date lastDailyDate = zyDailySettlementMapper.getLastDailyDateForUser(opId);
        if(lastDailyDate==null){
            lastDailyDate=DateUtil.pase("2021-06-04 00:00:00", "yyyy-MM-dd HH:mm:ss");
        }
        //测试代码
//        lastDailyDate = DateUtil.pase("2021-5-30 23:51:55.000", "yyyy-MM-dd HH:mm:ss");
//        now = DateUtil.pase("2021-5-31 14:56:11.000", "yyyy-MM-dd HH:mm:ss");
        zyDailySettlementVo.setLastDailyDate(DateUtil.fomart(lastDailyDate, "yyyy-MM-dd HH:mm:ss"));
        zyDailySettlementVo.setCurrentDate(DateUtil.fomart(now, "yyyy-MM-dd HH:mm:ss"));
        Map<String, Object> map = zyDailySettlementMapper.selectTotalChargeFromLegerFile(opId, lastDailyDate, now);
        setAttribute(zyDailySettlementVo, map);
        map = zyDailySettlementMapper.selectYjjFromDepositFile(opId, lastDailyDate, now);
        setAttribute(zyDailySettlementVo, map);
        map = zyDailySettlementMapper.selectHsJeAndHsCount(opId, lastDailyDate, now);
        setAttribute(zyDailySettlementVo, map);
        //设置预交金合计
        zyDailySettlementVo.sumtDepositTotal();
        List<ZdChequeType> zdChequeTypeList = zdChequeTypeMapper.selectAllZdChequeType();
        Map<String, String> chequeTypeMap = zdChequeTypeList.stream().collect(Collectors.toMap(ZdChequeType::getCode, ZdChequeType::getName));
        Map<String, String> employeeMap = new HashMap<>();
        List<Map<String, Object>> refunfZyDepositFileList = zyDailySettlementMapper.selectRefunfZyDepositFile(opId, lastDailyDate, now);
        setChargeZyDepositFileList(opId, zyDailySettlementVo, now, lastDailyDate, chequeTypeMap,employeeMap,refunfZyDepositFileList);
        setRefunfZyDepositFileList(opId, zyDailySettlementVo, now, lastDailyDate, chequeTypeMap,refunfZyDepositFileList);
        setZyChargeDetailList(opId, zyDailySettlementVo, now, lastDailyDate);
        setJsYjjDetailList(opId, zyDailySettlementVo, now, lastDailyDate,employeeMap);
        setJsfydjbb(opId, zyDailySettlementVo, now, lastDailyDate);
        return zyDailySettlementVo;
    }

    /**
     * 结算费用登记报表
     *
     * @param opId
     * @param zyDailySettlementVo
     * @param now
     * @param lastDailyDate
     */
    private void setJsfydjbb(String opId, ZyDailySettlementVo zyDailySettlementVo, Date now, Date lastDailyDate) {
        List<Map<String, Object>> jsfydjbb = zyDailySettlementMapper.selectJsFydjbb(ZyActpatient.ZY_ACTPATIENT, opId, lastDailyDate, now);
        List<Map<String, Object>> jsfydjbbInt = zyDailySettlementMapper.selectJsFydjbb(ZyActpatient.ZY_INACTPATIENT, opId, lastDailyDate, now);
        if (jsfydjbb == null) {
            jsfydjbb = jsfydjbbInt;
        } else {
            jsfydjbb.addAll(jsfydjbbInt);
        }
        if (jsfydjbb != null && jsfydjbb.size() > 0) {
            jsfydjbb.stream().forEach(j -> {
                String responceTypeStr = (String) j.get("responce_type");
                if (StringUtils.isNotBlank(responceTypeStr)) {
                    GenderEnum gender = GenderEnum.getGenderByCode(Integer.valueOf(responceTypeStr));
                    j.put("gender", gender == null ? "" : gender.name);
                }
                ResponceTypeEnum responceType = ResponceTypeEnum.getReportTypeByCode((String) j.get("responce_type"));
                j.put("responce_type_name", responceType == null ? "" : responceType.name);
                j.put("ward_name", zdUnitCodeService.queryDeptNameByIdInCache((String) j.get("ward")));
            });
        }
        zyDailySettlementVo.setJsfydjbb(jsfydjbb);
    }

    /**
     * 预交金收费列表
     *
     * @param opId
     * @param zyDailySettlementVo
     * @param now
     * @param lastDailyDate
     * @param chequeTypeMap
     */
    private void setChargeZyDepositFileList(String opId, ZyDailySettlementVo zyDailySettlementVo, Date now, Date lastDailyDate, Map<String, String> chequeTypeMap,Map<String, String> employeeMap,List<Map<String, Object>> refunfZyDepositFileList) {
        List<Map<String, Object>> chargeZyDepositFileList = zyDailySettlementMapper.selectChargeZyDepositFile(opId, lastDailyDate, now);
        if (chargeZyDepositFileList == null) {
            chargeZyDepositFileList = refunfZyDepositFileList;
        } else {
            chargeZyDepositFileList.addAll(refunfZyDepositFileList);
        }
        if (chargeZyDepositFileList != null && chargeZyDepositFileList.size() > 0) {
            chargeZyDepositFileList.stream().forEach(r -> {
                r.put("depo_type_name", chequeTypeMap.get(r.get("depo_type")));
                setOpName(employeeMap, r);
                r.put("ward_name", zdUnitCodeService.queryDeptNameByIdInCache((String) r.get("ward")));
            });
            Collections.sort(chargeZyDepositFileList, (o1, o2) -> {
                String receipt_no1 =(String)o1.get("receipt_no");
                String receipt_no2= (String)o2.get("receipt_no");
                return receipt_no1.compareTo(receipt_no2);
            });
            zyDailySettlementVo.setReceiptNoBegin((String) chargeZyDepositFileList.get(0).get("receipt_no"));
            zyDailySettlementVo.setReceiptNoEnd((String) chargeZyDepositFileList.get(chargeZyDepositFileList.size() - 1).get("receipt_no"));
        }
        zyDailySettlementVo.setChargeZyDepositFileList(chargeZyDepositFileList);
    }

    /**
     * 预交金退费列表
     *
     * @param opId
     * @param zyDailySettlementVo
     * @param now
     * @param lastDailyDate
     * @param chequeTypeMap
     */
    private void setRefunfZyDepositFileList(String opId, ZyDailySettlementVo zyDailySettlementVo, Date now, Date lastDailyDate, Map<String, String> chequeTypeMap,List<Map<String, Object>> refunfZyDepositFileList) {
        List<Map<String, Object>> deleteZyChargeDetailList = zyDailySettlementMapper.selectDeleteZyChargeDetail(opId, lastDailyDate, now);
        if (deleteZyChargeDetailList == null) {
            deleteZyChargeDetailList = refunfZyDepositFileList;
        } else {
            deleteZyChargeDetailList.addAll(refunfZyDepositFileList);
        }
        if (deleteZyChargeDetailList != null && deleteZyChargeDetailList.size() > 0) {
            deleteZyChargeDetailList.stream().forEach(r -> {
                r.put("depo_type_name", chequeTypeMap.get(r.get("depo_type")));
            });
        }
        zyDailySettlementVo.setRefunfZyDepositFileList(deleteZyChargeDetailList);
    }

    /**
     * 结算病人明细
     *
     * @param opId
     * @param zyDailySettlementVo
     * @param now
     * @param lastDailyDate
     */
    private void setZyChargeDetailList(String opId, ZyDailySettlementVo zyDailySettlementVo, Date now, Date lastDailyDate) {
        List<Map<String, Object>> zyChargeDetailList = zyDailySettlementMapper.selectZyChargeDetail(opId, lastDailyDate, now);
        if (zyChargeDetailList != null && zyChargeDetailList.size() > 0) {
            zyDailySettlementVo.setJsReceiptNoBegin((String) zyChargeDetailList.get(0).get("receipt_no"));
            zyDailySettlementVo.setJsReceiptNoEnd((String) zyChargeDetailList.get(zyChargeDetailList.size() - 1).get("receipt_no"));
        }
        zyDailySettlementVo.setZyChargeDetailList(zyChargeDetailList);
    }

    /**
     * 结算预交金明细
     *
     * @param opId
     * @param zyDailySettlementVo
     * @param now
     * @param lastDailyDate
     */
    private void setJsYjjDetailList(String opId, ZyDailySettlementVo zyDailySettlementVo, Date now, Date lastDailyDate,Map<String, String> employeeMap) {
        List<Map<String, Object>> jsYjjDetailList = zyDailySettlementMapper.selectJsYjjDetail(opId, lastDailyDate, now);
        if (jsYjjDetailList != null && jsYjjDetailList.size() > 0) {
            jsYjjDetailList.stream().forEach(r -> {
                setOpName(employeeMap, r);
            });
        }
        zyDailySettlementVo.setJsYjjDetailList(jsYjjDetailList);
    }

    /**
     * 设置操作员名称
     * @param employeeMap
     * @param r
     */
    private void setOpName(Map<String, String> employeeMap, Map<String, Object> r) {
        String opIdCode = (String) r.get("op_id_code");
        String name = employeeMap.get(opIdCode);
        if (StringUtils.isBlank(name)) {
            Employee employee = employeeMapper.selectByUserCode(opIdCode);
            if (employee != null) {
                employeeMap.put(opIdCode, employee.getEmployeeName());
                name = employee.getEmployeeName();
            }
        }
        r.put("op_id_name", name);
    }

    /**
     * 通过反射的方式设置属性值
     *
     * @param zyDailySettlementVo
     * @param map
     */
    private void setAttribute(ZyDailySettlementVo zyDailySettlementVo, Map<String, Object> map) {
        if (map != null && map.size() > 0) {
            for (String key : map.keySet()) {
                try {
                    Field field = zyDailySettlementVo.getClass().getDeclaredField(key);
                    field.setAccessible(true);
                    field.set(zyDailySettlementVo, map.get(key));
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("属性 【{}】设置失败，错误信息{}", key, e.getMessage());
                }
            }
        }
    }
}
