package com.saye.hospitalgd.scheduler.jobMethod;

import com.saye.hospitalgd.commons.date.DateDUtil;
import com.saye.hospitalgd.commons.getBean.GetBeanUtil;
import com.saye.hospitalgd.commons.log.LogUtil;
import com.saye.hospitalgd.commons.string.StringDUtil;
import com.saye.hospitalgd.model.Dicinfo;
import com.saye.hospitalgd.service.HisDetailService;
import com.saye.hospitalgd.service.HisInterFaceConfigService;
import com.saye.hospitalgd.service.OperatorService;
import com.saye.hospitalgd.service.historyLog.HisBillLogService;
import com.saye.hospitalgd.service.historyLog.impl.HisBillLogServiceImpl;
import com.saye.hospitalgd.service.impl.HisDetailServiceImpl;
import com.saye.hospitalgd.service.impl.HisInterFaceConfigServiceImpl;
import com.saye.hospitalgd.service.impl.OperatorServiceImpl;
import com.saye.hospitalgd.service.system.DicinfoService;
import com.saye.hospitalgd.service.system.ServiceParamsService;
import com.saye.hospitalgd.service.system.impl.DicinfoServiceImpl;
import com.saye.hospitalgd.service.system.impl.ServiceParamsServiceImpl;
import com.saye.hospitalgd.util.HisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * @author thuang
 * @version 1.0
 * @description: His获取数据方法（嘉禾）
 * @date 2021/9/30 13:41
 */
public class HISGetDataMethodByJH {

    private static final Logger log = LoggerFactory.getLogger(HISGetDataMethodByJH.class);



    public HashMap<Object,Object> getDate(String id, String name, String trade_date, String his_wsdl_id){
        HashMap<Object,Object> responseMap=new HashMap<>();
        String errCode="0";
        String errMsg="";

        HisBillLogService hisBillLogService = GetBeanUtil.getBean(HisBillLogServiceImpl.class);
        HisDetailService hisDetailService = GetBeanUtil.getBean(HisDetailServiceImpl.class);
        OperatorService operatorService = GetBeanUtil.getBean(OperatorServiceImpl.class);
        DicinfoService dicinfoService = GetBeanUtil.getBean(DicinfoServiceImpl.class);

        ServiceParamsService serviceParamsService = GetBeanUtil.getBean(ServiceParamsServiceImpl.class);

        HisInterFaceConfigService hisInterFaceConfigService = GetBeanUtil.getBean(HisInterFaceConfigServiceImpl.class);



        try {
            //查询需要用到的参数

            //his接口地址
            List<HashMap<Object, Object>> hisConfigList = hisInterFaceConfigService.findConfigById(his_wsdl_id);
            String his_wsdl = StringDUtil.changeNullToEmpty(hisConfigList.get(0).get("HIS_INTERFACE_WSDL"));
            String code = StringDUtil.changeNullToEmpty(hisConfigList.get(0).get("CODE"));

            //现金支付方式
            List<HashMap<Object, Object>> serviceParams = serviceParamsService.findParamValByParamCode("cash_code");
            String cash_code = StringDUtil.changeNullToEmpty(serviceParams.get(0).get("PARAM_VAL"));

            //his端其他支付方式 也单独处理 因为里面没有唯一id 且都是支票记录
            String zhipiao="无";

            //操作员号
            List<HashMap<Object,Object>> operators = operatorService.findAllOperator(new HashMap<Object,Object>());
            //将操作员号用逗号连接
            String operatorsCodeStr="";
            for (int i = 0; i < operators.size(); i++) {
                HashMap<Object, Object> hashMap = operators.get(i);
                operatorsCodeStr =operatorsCodeStr + StringDUtil.changeNullToEmpty(hashMap.get("HISOPERCODE")) + ",";
            }
            if (operatorsCodeStr.length()>0){
                operatorsCodeStr=operatorsCodeStr.substring(0,operatorsCodeStr.length()-1);
            }

            log.info("HIS获取数据定时任务【"+name+"】开始执行，操作员号：【"+operatorsCodeStr+"】，获取日期：【"+trade_date+"】");

            //全部支付方式
            List<Dicinfo> pay_type = dicinfoService.findDicinfoTreeNodeList("PAY_TYPE");
            HashMap<String, String> payTypeMap = new HashMap<>();
            for (Dicinfo dicinfo : pay_type) {
                payTypeMap.put(dicinfo.getDicname(), dicinfo.getDicvalue());
            }

            //开始结束时间
            //TODO 目前his测试数据库只有2024年有账单数据暂时入参时间暂时写死,后续上线后需要改回动参
            String startTime="";
            String endTime="";
            if ("".equals(trade_date)) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());
                calendar.add(Calendar.DATE, -1);
                Date time = calendar.getTime();

                startTime = DateDUtil.DateToStr(DateDUtil.yyyy_MM_dd, time) + " 00:00:00";
                endTime = DateDUtil.DateToStr(DateDUtil.yyyy_MM_dd, new Date()) + " 00:00:00";
                trade_date=DateDUtil.DateToStr(DateDUtil.yyyy_MM_dd, time);
            }else {
                startTime = trade_date + " 00:00:00";
                Date date = DateDUtil.strToDate(DateDUtil.yyyy_MM_dd, trade_date);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date);
                calendar.add(Calendar.DATE, 1);
                endTime = DateDUtil.DateToStr(DateDUtil.yyyy_MM_dd, calendar.getTime()) + " 00:00:00";
            }

            //组织request
//            startTime="2024-08-06 15:33:12";
//            endTime="2024-08-07 15:33:12";
            String requestStr="";
            requestStr="<Request>" +
                    " <HisOperNum>"+ operatorsCodeStr +"</HisOperNum>" +
                    " <StartTime>"+startTime+"</StartTime>" +
                    " <EndTime>"+endTime+"</EndTime>" +
                    "</Request>";


            //获取数据
            HisUtil hisUtil = new HisUtil();
            HashMap<String, String> histData = hisUtil.getHisDataByHY(his_wsdl, code, requestStr);
            errCode = histData.get("errCode");
            if (!"0".equals(errCode)){
                errMsg=histData.get("errMsg");
            }else {
                String dataStr = histData.get("dataStr");

                //分析数据，判断调用正确与否
                HashMap<String, Object> hisBillResult = hisUtil.managerDataStrByHY(dataStr);
                errCode = StringDUtil.changeNullToEmpty(hisBillResult.get("errCode"));
                if (!"0".equals(errCode)){
                    errMsg=StringDUtil.changeNullToEmpty(hisBillResult.get("errMsg"));
                }else {
                    List<HashMap<Object,Object>> hisBillList  = (List<HashMap<Object,Object>>)hisBillResult.get("addList");

                    //存一份his原始的
                    hisDetailService.insertHisBillOriginalHY(hisBillList,trade_date,his_wsdl_id);

                    //将原始的转换成统一格式
                    List<HashMap<Object,Object>> newAddList= new ArrayList<>();

                    for (int i = 0; i < hisBillList.size(); i++) {
                        HashMap<Object, Object> hisBillHashMap = hisBillList.get(i);

                        //获取PowerTranID和ReceiptNO作为唯一标识
                        String powerTranID = StringDUtil.changeNullToEmpty(hisBillHashMap.get("powerTranID"));
                        String receiptNO = StringDUtil.changeNullToEmpty(hisBillHashMap.get("receiptNO"));
                        // String hisTransId = StringDUtil.changeNullToEmpty(hisBillHashMap.get("hisTransId")); // 已在HisUtil中赋值，此处不再重复获取
                        
                        // 修改跳过逻辑：只有当关键业务信息都缺失时才跳过
                        // 检查是否有足够的业务信息来处理这条记录
                        String patientId = StringDUtil.changeNullToEmpty(hisBillHashMap.get("patientID"));
                        String amount = StringDUtil.changeNullToEmpty(hisBillHashMap.get("amount"));
                        String tradeTime = StringDUtil.changeNullToEmpty(hisBillHashMap.get("tradeTime"));
                        
                        // 提取新增字段：清算类别、险种类型、医保账户金额、医保统筹金额、自费金额
                        String clrType = StringDUtil.changeNullToEmpty(hisBillHashMap.get("clrType"));
                        String insutype = StringDUtil.changeNullToEmpty(hisBillHashMap.get("insutype"));
                        String ybzhAmount = StringDUtil.changeNullToEmpty(hisBillHashMap.get("ybzhAmount"));
                        String ybtcAmount = StringDUtil.changeNullToEmpty(hisBillHashMap.get("ybtcAmount"));
                        String zfAmount = StringDUtil.changeNullToEmpty(hisBillHashMap.get("zfAmount"));
                        
                        // 只有当缺少关键业务信息时才跳过（患者ID、金额、交易时间都为空）
                        if ("".equals(patientId) && "".equals(amount) && "".equals(tradeTime)){
                            log.warn("跳过缺少关键业务信息的记录: powerTranID={}, receiptNO={}", 
                                powerTranID, receiptNO);
                            continue;
                        }
                        
                        // 对于没有唯一标识的记录，记录警告但继续处理
                        if ("".equals(powerTranID) && "".equals(receiptNO)){
                            log.warn("处理无唯一标识的记录: patientID={}, amount={}, tradeTime={}", 
                                patientId, amount, tradeTime);
                        }

                        //数据类型 1-门诊 2-住院 无需修改
                        String payMethod = StringDUtil.changeNullToEmpty(hisBillHashMap.get("visitzOrg"));

                        //业务类型 0发病历1办卡2就诊卡充值3当日挂号-3 挂号退费4门诊缴费-4 单据退费5现场预约-5 预约退费6预约取号7住院缴费-7出院结算退费-77 预存作废退费
                        String bizType = StringDUtil.changeNullToEmpty(hisBillHashMap.get("bizType"));

                        String tradingStatus = "1";
                        try {
                            if (new BigDecimal(amount).compareTo(BigDecimal.ZERO) < 0) {
                                tradingStatus = "2";
                            }
                        } catch (Exception ex) {
                            tradingStatus = "1";
                        }

                        //支付方式 严格按照字典表转换
                        String originalPayType = StringDUtil.changeNullToEmpty(hisBillHashMap.get("payType"));
                        
                        // 保持接口原始的医保账户金额和统筹金额，不做按支付类型的替换或清零
                        
                        // 转换PayType为标准编码
                        String payType = convertPayTypeByDictionary(originalPayType, payTypeMap);

                        //操作员
                        String hisOperCode = StringDUtil.changeNullToEmpty(hisBillHashMap.get("hisOperCode"));

                        //说明
                        String remarks = "";

                        //银商订单号：优先使用PowerTranID，如果为空则使用ReceiptNO
                        String platformTransId = powerTranID;
                        if ("".equals(platformTransId)) {
                            platformTransId = receiptNO;
                        }

                        //患者姓名
                        String patientName = StringDUtil.changeNullToEmpty(hisBillHashMap.get("patientName"));

                        //交易日期
                        String thistrade_date = StringDUtil.changeNullToEmpty(hisBillHashMap.get("trade_date"));

                        //接口厂商
                        HashMap<Object,Object> addMap=new HashMap<>();
                        addMap.put("payMethod",payMethod);
                        addMap.put("tradingStatus",tradingStatus);
                        addMap.put("bizType",bizType);
                        addMap.put("payType",payType);
                        addMap.put("tradeTime",tradeTime);
                        addMap.put("hisOperCode",hisOperCode);
                        addMap.put("amount",amount);
                        addMap.put("remarks",remarks);
                        addMap.put("platformTransId",platformTransId);
                        addMap.put("patientId",patientId);
                        addMap.put("patientName",patientName);
                        addMap.put("trade_date",thistrade_date);
                        addMap.put("his_wsdl_id",his_wsdl_id);
                        addMap.put("clrType",clrType);         // 清算类别
                        addMap.put("insutype",insutype);       // 险种类型
                        addMap.put("ybzhAmount",ybzhAmount);   // 医保账户金额
                        addMap.put("ybtcAmount",ybtcAmount);   // 医保统筹金额
                        addMap.put("zfAmount",zfAmount);       // 自费金额（混合支付中的自费部分）
                        addMap.put("hisTransId",receiptNO);     // HisTransId字段使用ReceiptNO的值

                        // 不再合并现金和支票记录，直接保留原始数据
                        // 因为有些医保账户余额不足时会用现金支付，但仍然属于医保相关记录
                        // 合并会导致清算类别(clrType)和险种(insutype)信息丢失
                        newAddList.add(addMap);
                    }

                    //存一份his针对要调整的字段修改的
                    hisDetailService.insertHisBillList(newAddList,trade_date,his_wsdl_id);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            errCode="999";
            errMsg="执行定时任务【"+name+"】出错，原因："+e.getMessage();
        }

        //存储记录
        try {
            HashMap<Object,Object> addMap=new HashMap<>();
            addMap.put("trade_date",trade_date);
            addMap.put("quartz_id",id);
            addMap.put("quartz_name",name);
            addMap.put("his_wsdl_id",his_wsdl_id);

            if ("0".equals(errCode)){
                addMap.put("is_ok","1");
            }else {
                addMap.put("is_ok","0");
            }

            addMap.put("modify_time",DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd_HH_mm_ss));
            hisBillLogService.insertHisbillGetinfo(addMap);

        }catch (Exception e){
            e.printStackTrace();
            errCode="999";
            errMsg="保存His获取的记录失败，原因"+e.getMessage();
        }

        if (!"0".equals(errCode)){
            try {
                //记录日志
                LogUtil.error(this.getClass(), errMsg);

            }catch (Exception e){
                e.printStackTrace();
            }
        }

        responseMap.put("errCode",errCode);
        responseMap.put("errMsg",errMsg);
        return responseMap;
    }
    
    /**
     * 严格按照字典表将HIS原始支付方式转换为标准的PayType编码
     * @param originalPayType HIS原始支付方式
     * @param payTypeMap 支付方式字典映射 (dicname -> dicvalue)
     * @return 标准PayType编码
     */
    private String convertPayTypeByDictionary(String originalPayType, HashMap<String, String> payTypeMap) {
        if (originalPayType == null || originalPayType.trim().isEmpty()) {
            return "4"; // 其他（根据用户自定义编码）
        }
        
        String payTypeName = originalPayType.trim();
        
        // 严格按照字典表匹配四种支付方式
        String payTypeValue = payTypeMap.get(payTypeName);
        
        if (payTypeValue != null && !payTypeValue.isEmpty()) {
            return payTypeValue;
        }
        
        // 如果字典表中没有精确匹配，记录日志并返回"其他"
        log.warn("未在字典表中找到支付方式映射: [{}], 已转换为其他支付方式", payTypeName);
        return "4"; // 其他（根据用户自定义编码）
    }
}
