package com.openhis.web.paymentmanage.appservice.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.core.common.core.domain.R;
import com.core.common.enums.TenantOptionDict;
import com.core.common.exception.ServiceException;
import com.core.common.utils.SecurityUtils;
import com.core.web.util.TenantOptionUtil;
import com.openhis.administration.domain.Practitioner;
import com.openhis.administration.service.IPractitionerService;
import com.openhis.financial.domain.PaymentReconciliation;
import com.openhis.financial.domain.ThreePartPayCallBack;
import com.openhis.financial.service.IPaymentRecDetailService;
import com.openhis.financial.service.IPaymentReconciliationService;
import com.openhis.financial.service.ThreePartPayCallBackService;
import com.openhis.web.paymentmanage.appservice.ThreePartPayService;
import com.openhis.yb.dto.BaseInfo;
import com.openhis.yb.dto.BaseParam;
import com.openhis.yb.dto.PaymentDetailDto;
import com.openhis.yb.dto.ThreePartPayDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class ThreePartPayServiceImpl implements ThreePartPayService {

    @Autowired
    private IPractitionerService practitionerService;
    @Autowired
    private IPaymentRecDetailService paymentRecDetailService;
    @Autowired
    private IPaymentReconciliationService paymentReconciliationService;
    @Autowired
    private ThreePartPayCallBackService threePartPayCallBackService;
    @Autowired
    private ThreePartSimpleFieldMappingService threePartSimpleFieldMappingService;


    @Override
    public R<?> payFor(ThreePartPayDto threePartPayDto) {
        String threePartUrl = TenantOptionUtil.getOptionContent(TenantOptionDict.THREE_PART_PAY_URL);
        //String threePartUrl = "http://127.0.0.1:19994/?MSG=EXEC&yylx=02&posjh=&posygh=&jylx=00&je={je}&yjyrq=&yjyckh=&ypzh=&lrcjy=&cm={cm}&ysddh=&erpddh=&body=";
        String threePartParam = TenantOptionUtil.getOptionContent(TenantOptionDict.THREE_PART_PARAM);
        JSONObject jsonObject = JSON.parseObject(threePartParam);

        //订单号及订单信息
        Long paymentId = threePartPayDto.getId();
        PaymentReconciliation paymentReconciliation = paymentReconciliationService.getById(paymentId);

        //金额处理
        BigDecimal amount = BigDecimal.ZERO;
        for (PaymentDetailDto paymentDetail : threePartPayDto.getPaymentDetails()) {
            if(threePartPayDto.getIndex().equals(paymentDetail.getPayEnum())){
                amount = paymentDetail.getAmount();
            }
        }
        amount = amount.multiply(new BigDecimal("100"));
        String amountResult = String.format("%010d", Integer.parseInt(amount.toString()));

        //款员信息查询
        Practitioner practitioner = practitionerService.getPractitionerByUserId(SecurityUtils.getLoginUser().getUserId());

        //获取支付码
        String txtCode = threePartPayDto.getTxtCode();

        //获取参数
        Map<String, String> paramMap = this.getParamMap(jsonObject, practitioner, null, paymentReconciliation, amountResult, txtCode);

        //获取完整url
        String url = renderTemplateSafe(threePartUrl, paramMap);

        String result = httpGet(url);

        String threePartMapping = threePartSimpleFieldMappingService.reverseMap("threePartMapping", result);

        threePartPayCallBackService.save(JSON.parseObject(threePartMapping,ThreePartPayCallBack.class));

        return R.ok();
    }


    /**
     * 拼接参数
     * @param jsonObject 配置信息
     * @param practitioner 款员信息
     * @param threePartPayCallBack 原订单
     * @param amountResult 金额
     * @param txtCode 支付码
     * @return
     */
    private Map<String,String> getParamMap(JSONObject jsonObject,Practitioner practitioner, ThreePartPayCallBack threePartPayCallBack,PaymentReconciliation paymentReconciliation,String amountResult,String txtCode){
        Map<String, String> paramMap = new HashMap<>();

        //款员信息
        if(practitioner!=null){
            String posNoKey = jsonObject.getString("posNo");//pos机编码
            if(posNoKey!=null){
                paramMap.put(posNoKey,practitioner.getPosNo());
            }
            String userIdKey = jsonObject.getString("userId");
            if(userIdKey!=null){
                paramMap.put(userIdKey,practitioner.getId().toString());
            }
            String userNameKey = jsonObject.getString("userName");
            if(userNameKey!=null){
                paramMap.put(userNameKey,practitioner.getName());
            }
        }

        //原账单信息
        if(threePartPayCallBack!=null){
            String bankOrderIdKey = jsonObject.getString("bankOrderId");
            if(bankOrderIdKey!=null){
                paramMap.put(bankOrderIdKey,threePartPayCallBack.getTradeNo());//银行订单号
            }
            String payWayOrderIdKey = jsonObject.getString("payWayOrderId");
            if(payWayOrderIdKey!=null){
                paramMap.put(payWayOrderIdKey,threePartPayCallBack.getTransNo());//支付渠道订单号
            }
            String tranTypeKey = jsonObject.getString("tranType");
            if(tranTypeKey!=null){
                paramMap.put(tranTypeKey,threePartPayCallBack.getTranType());//交易类型
            }
            String payTypeKey = jsonObject.getString("payType");
            if(payTypeKey!=null){
                paramMap.put(payTypeKey,threePartPayCallBack.getPayType());//支付方式
            }
            String traceNoKey = jsonObject.getString("traceNo");
            if(payWayOrderIdKey!=null){
                paramMap.put(traceNoKey,threePartPayCallBack.getTraceNo());//终端流水号
            }
            String txnTimeKey = jsonObject.getString("txnTime");
            if(payWayOrderIdKey!=null){
                paramMap.put(txnTimeKey,threePartPayCallBack.getTxnTime());//交易时间
            }
            String merTradeNoKey = jsonObject.getString("merTradeNo");
            if(payWayOrderIdKey!=null){
                paramMap.put(merTradeNoKey,threePartPayCallBack.getMerTradeNo());//商户系统订单号
            }
        }

        if(paymentReconciliation!=null){
            String paymentIdKey = jsonObject.getString("paymentId");
            if(paymentIdKey!=null){
                paramMap.put(paymentIdKey,paymentReconciliation.getId().toString());//his系统订单号
            }
        }

        String amountResultKey = jsonObject.getString("amountResult");
        String txtCodeKey = jsonObject.getString("txtCode");

        if(amountResult!=null){
            paramMap.put(amountResultKey,amountResult);//金额
        }
        if(txtCode!=null){
            paramMap.put(txtCodeKey,txtCode);//扫码
        }
        return paramMap;
    }
    /**
     * 安全替换，避免空指针
     */
    private String renderTemplateSafe(String template, Map<String, String> params) {
        if (template == null) return "";
        if (params == null) params = new HashMap<>();

        String result = template;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String placeholder = "{" + entry.getKey() + "}";
            String value = entry.getValue() != null ? entry.getValue().toString() : "";
            // 使用 replace 而不是 replaceAll，避免正则表达式特殊字符问题
            result = result.replace(placeholder, value);
        }

        return result;
    }

    /**
     * 发送http请求（2025/05/02经测试，若以自带的工具类发送请求失败，故使用原peis系统中成功调用的写法重新封装）
     *
     * @param url 路径
     * @return
     */
    private String httpGet(String url) {
        String resultString = "";
        // 创建Http请求（2025/10/13 师大会超时故此由30000-》60000）
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(90000).setConnectionRequestTimeout(90000)
                .setSocketTimeout(90000).build();
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
        CloseableHttpResponse response = null;
        // 发送请求
        try {
            HttpGet httpGet = new HttpGet(url);
            // 执行http请求
            response = httpClient.execute(httpGet);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("Http请求异常，请稍后再试。");
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }
}
