package shop.alien.lawyer.payment.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.jdbc.Null;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import shop.alien.entity.result.R;
import shop.alien.entity.store.LawyerConsultationOrder;
import shop.alien.entity.store.RefundRecord;
import shop.alien.entity.store.StoreAliPayRefundLog;
import shop.alien.mapper.LawyerConsultationOrderMapper;
import shop.alien.lawyer.payment.PaymentStrategy;
import shop.alien.lawyer.service.RefundRecordService;
import shop.alien.lawyer.service.StoreAliPayRefundLogService;
import shop.alien.util.common.UniqueRandomNumGenerator;
import shop.alien.util.common.UrlEncode;
import shop.alien.util.common.constant.PaymentEnum;
import shop.alien.util.system.OSUtil;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * 支付宝支付策略
 *
 * @author lyx
 * @date 2025/11/20
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AlipayPaymentStrategyImpl implements PaymentStrategy {

    /**
     * 商家端appId
     */
    @Value("${payment.aliPay.business.appId}")
    private String businessAppId;

    /**
     * 商家端app私钥
     */
    @Value("${payment.aliPay.business.appPrivateKey}")
    private String businessAppPrivateKey;

    /**
     * 商家端app公钥
     */
    @Value("${payment.aliPay.business.appPublicKey}")
    private String businessAppPublicKey;

    /**
     * windows应用公钥证书文件路径
     */
    @Value("${payment.aliPay.business.win.appCertPath}")
    private String businessWinAppCertPath;

    /**
     * windows支付宝公钥证书文件路径
     */
    @Value("${payment.aliPay.business.win.alipayPublicCertPath}")
    private String businessWinAlipayPublicCertPath;

    /**
     * windows支付宝根证书文件路径
     */
    @Value("${payment.aliPay.business.win.alipayRootCertPath}")
    private String businessWinAlipayRootCertPath;

    /**
     * linux应用公钥证书文件路径
     */
    @Value("${payment.aliPay.business.linux.appCertPath}")
    private String businessLinuxAppCertPath;

    /**
     * linux支付宝公钥证书文件路径
     */
    @Value("${payment.aliPay.business.linux.alipayPublicCertPath}")
    private String businessLinuxAlipayPublicCertPath;

    /**
     * linux支付宝根证书文件路径
     */
    @Value("${payment.aliPay.business.linux.alipayRootCertPath}")
    private String businessLinuxAlipayRootCertPath;

    /**
     * 支对称加密算法密钥
     */
    @Value("${ali.aes.encryptKey}")
    private String encryptKey;
    /**
     * 支付宝网关地址
     */
    @Value("${payment.aliPay.host}")
    private String aliPayApiHost;

    private final StoreAliPayRefundLogService storeAliPayRefundLogService;

    private final RefundRecordService refundRecordService;

    private final LawyerConsultationOrderMapper lawyerConsultationOrderMapper;


    /**
     * 填写阿里配置
     *
     * @return AlipayConfig
     */
    private AlipayConfig setAlipayConfig(String type) {
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl(aliPayApiHost);
        alipayConfig.setAppId(businessAppId);
        alipayConfig.setPrivateKey(businessAppPrivateKey);
        alipayConfig.setFormat("json");
        alipayConfig.setCharset("UTF-8");
        alipayConfig.setSignType("RSA2");
        if ("windows".equals(OSUtil.getOsName())) {
            alipayConfig.setAppCertPath(businessWinAppCertPath);
            alipayConfig.setAlipayPublicCertPath(businessWinAlipayPublicCertPath);
            alipayConfig.setRootCertPath(businessWinAlipayRootCertPath);
        } else {
            alipayConfig.setAppCertPath(businessLinuxAppCertPath);
            alipayConfig.setAlipayPublicCertPath(businessLinuxAlipayPublicCertPath);
            alipayConfig.setRootCertPath(businessLinuxAlipayRootCertPath);
        }
        if ("aes".equals(type)) {
            alipayConfig.setEncryptType("AES");
            alipayConfig.setEncryptKey(encryptKey);
        }
        return alipayConfig;
    }

    @Override
    public R createPrePayOrder(String price, String subject) throws Exception {
        log.info("创建支付宝预支付订单，价格：{}，描述：{}", price, subject);
        // 参数验证
        if (price == null || price.trim().isEmpty()) {
            return R.fail("价格不能为空");
        }
        if (subject == null || subject.trim().isEmpty()) {
            return R.fail("订单描述不能为空");
        }
        try {
            BigDecimal amount = new BigDecimal(price);
            if (amount.compareTo(BigDecimal.ZERO) <= 0) {
                return R.fail("价格必须大于0");
            }
        } catch (NumberFormatException e) {
            return R.fail("价格格式不正确");
        }
        // 生成订单号
        String orderNo = UniqueRandomNumGenerator.generateUniqueCode(19);
        // 构建预支付请求
        AlipayTradeAppPayRequest request = buildPrePayRequest(price, subject,orderNo);
        
        try {
            // 调用支付宝接口创建预支付订单
            JSONObject result = prePayOrderRun(request);
            result.put("orderNo", orderNo);
            log.info("支付宝预支付订单创建成功，商家订单号：{}", orderNo);
            return R.data(result);
        } catch (AlipayApiException e) {
            log.error("支付宝预支付失败，错误码：{}，错误信息：{}", e.getErrCode(), e.getErrMsg());
            return R.fail("支付宝预支付失败：" + e.getErrMsg());
        }
    }

    @Override
    public R<Object> handleNotify(String notifyData) throws Exception {
        log.info("处理支付宝支付通知，通知数据：{}", notifyData);
        // TODO: 实现支付通知处理逻辑
        // 1. 验证签名
        // 2. 解析通知数据
        // 3. 更新订单状态
        // 4. 返回处理结果
        return R.fail("功能尚未实现");
    }

    @Override
    public R<Object> searchOrderByOutTradeNoPath(String transactionId,Integer id ,String orderStr) throws Exception {
        try {

            //根据id把transactionId和orderStr更新到lawyer_consultation_order表中

            LambdaUpdateWrapper<LawyerConsultationOrder> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(LawyerConsultationOrder::getId, id);
            updateWrapper.set(LawyerConsultationOrder::getAlipayNo, transactionId);
            updateWrapper.set(LawyerConsultationOrder::getOrderStr, orderStr);

            int a=lawyerConsultationOrderMapper.update(null, updateWrapper);

            if (a>0){
                log.info("更新订单成功");
            }

            AlipayClient alipayClient = new DefaultAlipayClient(setAlipayConfig(null));
            // 2. 构造查询请求
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();

            // 设置biz_content（JSON格式）
            JSONObject bizContent = new JSONObject();
            if (StringUtils.isNotBlank(transactionId)) {
                bizContent.put("out_trade_no", transactionId);
            }
//            if (StringUtils.isNotBlank(tradeNo)) {
//                bizContent.put("trade_no", tradeNo);
//            }
            request.setBizContent(bizContent.toJSONString());

            // 3. 调用接口并获取响应
            AlipayTradeQueryResponse response = alipayClient.certificateExecute(request);
            if (response.isSuccess()) {
                // 4. 解析支付状态
                String tradeStatus = response.getTradeStatus();
                log.info("订单查询成功，支付状态：" + tradeStatus);

                // 支付状态说明：
                // WAIT_BUYER_PAY：等待买家付款
                // TRADE_CLOSED：交易关闭（超时未支付/已取消）
                // TRADE_SUCCESS：支付成功（即时到账/普通转账）
                // TRADE_FINISHED：交易完成（不可退款的场景，如即时到账）
                if ("TRADE_SUCCESS".equals(tradeStatus)) {
                    return R.success("支付成功");
                } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                    return R.fail("交易已关闭");
                } else if ("WAIT_BUYER_PAY".equals(tradeStatus)) {
                    return R.fail("等待买家付款");
                } else if ("TRADE_FINISHED".equals(tradeStatus)) {
                    return R.success("交易完成");
                }
                return R.success("订单状态：" + tradeStatus);
            } else {
                return R.fail("订单查询失败：" + response.getMsg() + "(" + response.getSubMsg() + ")");
            }
        } catch (AlipayApiException e) {
            log.error("支付宝订单查询异常", e);
            return R.fail("查询异常：" + e.getMessage());
        }

    }

    @Override
    public String handleRefund(Map<String, String> params) throws Exception {
        log.info("处理支付宝退款请求，参数：{}", params);
        try {
            AlipayTradeRefundRequest request = buildRefundRequest(params);
            AlipayTradeRefundResponse response = refundRun(request);
            String refundReslut = "";
            JSONObject responseBody = JSONObject.parseObject(response.getBody());
            JSONObject refundResponse = responseBody.getJSONObject("alipay_trade_refund_response");
            
            if (response.isSuccess()) {
                refundReslut = "调用成功";
                // 保存退款信息进入到支付宝退款记录表（保留原有逻辑）
                StoreAliPayRefundLog refundLog = new StoreAliPayRefundLog();
                // 响应基本信息
                refundLog.setResponseCode(refundResponse.getString("code"));
                refundLog.setResponseMsg(refundResponse.getString("msg"));
                // 买家信息
                refundLog.setBuyerLogonId(refundResponse.getString("buyer_logon_id"));
                refundLog.setBuyerOpenId(refundResponse.getString("buyer_open_id"));
                // 资金变动信息
                refundLog.setFundChange(refundResponse.getString("fund_change"));
                // 订单信息
                refundLog.setOutTradeNo(refundResponse.getString("out_trade_no"));
                refundLog.setTradeNo(refundResponse.getString("trade_no"));
                // 退款金额信息
                refundLog.setRefundFee(refundResponse.getString("refund_fee"));
                refundLog.setSendBackFee(refundResponse.getString("send_back_fee"));
                // 退款渠道明细（转换为JSON字符串）
                if (refundResponse.containsKey("refund_detail_item_list")) {
                    JSONArray refundDetailList = refundResponse.getJSONArray("refund_detail_item_list");
                    if (refundDetailList != null) {
                        refundLog.setRefundDetailItemList(JSON.toJSONString(refundDetailList));
                    }
                }
                // 退款时间（字符串转Date）
                String gmtRefundPayStr = refundResponse.getString("gmt_refund_pay");
                if (StringUtils.isNotBlank(gmtRefundPayStr)) {
                    try {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        refundLog.setGmtRefundPay(sdf.parse(gmtRefundPayStr));
                    } catch (ParseException e) {
                        log.warn("解析退款时间失败: {}", gmtRefundPayStr, e);
                    }
                }
                // 退款原因和部分退款编号（从请求参数中获取）
                refundLog.setRefundReason(params.get("refundReason"));
                refundLog.setOutRequestNo(params.get("partialRefundCode"));
                // 证书和签名信息
                refundLog.setAlipayCertSn(responseBody.getString("alipay_cert_sn"));
                refundLog.setSign(responseBody.getString("sign"));
                // 标准字段
                refundLog.setDeleteFlag(0);
                refundLog.setCreatedTime(new Date());
                storeAliPayRefundLogService.save(refundLog);
                
                // 保存到通用退款记录表
                try {
                    RefundRecord refundRecord = buildRefundRecordFromAlipayResponse(refundResponse, responseBody, params);
                    if (refundRecord != null) {
                        // 检查是否已存在，避免重复插入
                        long count = refundRecordService.lambdaQuery()
                                .eq(RefundRecord::getOutRefundNo, refundRecord.getOutRefundNo())
                                .count();
                        if (count == 0) {
                            refundRecordService.save(refundRecord);
                            log.info("支付宝退款记录已保存到RefundRecord表，商户退款单号：{}", refundRecord.getOutRefundNo());
                        } else {
                            log.info("支付宝退款记录已存在，跳过插入，商户退款单号：{}", refundRecord.getOutRefundNo());
                        }
                    }
                } catch (Exception e) {
                    log.error("保存支付宝退款记录到RefundRecord表失败", e);
                    // 不抛出异常，避免影响原有逻辑
                }
            } else {
                log.warn("AliPayConfig.processRefund ERROR Msg={}", response.getBody());
                refundReslut = refundResponse.getString("sub_msg");
                
                // 保存失败记录到通用退款记录表
                try {
                    RefundRecord refundRecord = buildRefundRecordFromAlipayError(refundResponse, responseBody, params);
                    if (refundRecord != null) {
                        // 检查是否已存在，避免重复插入
                        long count = refundRecordService.lambdaQuery()
                                .eq(RefundRecord::getOutRefundNo, refundRecord.getOutRefundNo())
                                .count();
                        if (count == 0) {
                            refundRecordService.save(refundRecord);
                            log.info("支付宝退款失败记录已保存到RefundRecord表，商户退款单号：{}", refundRecord.getOutRefundNo());
                        } else {
                            log.info("支付宝退款失败记录已存在，跳过插入，商户退款单号：{}", refundRecord.getOutRefundNo());
                        }
                    }
                } catch (Exception e) {
                    log.error("保存支付宝退款失败记录到RefundRecord表失败", e);
                }
            }
            return refundReslut;
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String getType() {
        return PaymentEnum.ALIPAY.getType();
    }


    /**
     * 构建预支付请求
     */
    private AlipayTradeAppPayRequest buildPrePayRequest(String price, String subject,String outTradeNo) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            model.setOutTradeNo(outTradeNo);
            model.setTotalAmount(price);
            model.setSubject(subject);
            model.setPassbackParams(UrlEncode.getUrlEncode(dateFormat.toString()));
            request.setBizModel(model);
            return request;
    }

    /**
     * 构建退款请求
     */
    private AlipayTradeRefundRequest buildRefundRequest(Map<String, String> params) {
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(params.get("outTradeNo"));
        model.setRefundAmount(params.get("refundAmount"));
        model.setRefundReason(params.get("refundReason"));
        if (StringUtils.isNotBlank(params.get("partialRefundCode"))) {
            model.setOutRequestNo(params.get("partialRefundCode"));
        }
        request.setBizModel(model);
        return request;
    }

    /**
     * 执行预支付订单请求
     */
    private JSONObject prePayOrderRun(AlipayTradeAppPayRequest request) throws AlipayApiException {
        JSONObject jsonObject = new JSONObject();
        AlipayClient alipayClient = new DefaultAlipayClient(setAlipayConfig(null));
        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
        String orderStr = "";
        if (response.isSuccess()) {
            orderStr = response.getBody();
        } else {
            System.out.println("调用失败 response：" + response);
            orderStr = "调用失败";
        }
        jsonObject.put("orderStr", orderStr);
        return jsonObject;
    }



    /**
     * 执行退款请求
     */
    private AlipayTradeRefundResponse refundRun(AlipayTradeRefundRequest request) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(setAlipayConfig(null));
        AlipayTradeRefundResponse response = alipayClient.certificateExecute(request);
        return response;
    }

    /**
     * 从支付宝退款响应构建RefundRecord对象（成功情况）
     */
    private RefundRecord buildRefundRecordFromAlipayResponse(JSONObject refundResponse, JSONObject responseBody, Map<String, String> params) {
        try {
            RefundRecord record = new RefundRecord();
            
            // 基本信息
            record.setPayType(PaymentEnum.ALIPAY.getType());
            record.setOutTradeNo(refundResponse.getString("out_trade_no"));
            record.setTransactionId(refundResponse.getString("trade_no"));
            // 部分退款编号作为商户退款单号，如果没有则生成一个
            String outRefundNo = params.get("partialRefundCode");
            if (StringUtils.isBlank(outRefundNo)) {
                outRefundNo = UniqueRandomNumGenerator.generateUniqueCode(19);
            }
            record.setOutRefundNo(outRefundNo);
            record.setRefundId(null); // 支付宝没有单独的退款单号
            record.setRefundStatus("SUCCESS");
            
            // 金额信息（支付宝返回的是元，需要转换为分）
            String refundFeeStr = refundResponse.getString("refund_fee");
            String sendBackFeeStr = refundResponse.getString("send_back_fee");
            if (StringUtils.isNotBlank(refundFeeStr)) {
                record.setRefundAmount(new BigDecimal(refundFeeStr).multiply(new BigDecimal(100)).longValue());
            }
            if (StringUtils.isNotBlank(sendBackFeeStr)) {
                record.setActualRefundAmount(new BigDecimal(sendBackFeeStr).multiply(new BigDecimal(100)).longValue());
            }
            // 订单总金额从params获取，如果没有则从退款金额推算
            String totalAmountStr = params.get("totalAmount");
            if (StringUtils.isNotBlank(totalAmountStr)) {
                record.setTotalAmount(new BigDecimal(totalAmountStr).multiply(new BigDecimal(100)).longValue());
            }
            record.setCurrency("CNY");
            
            // 退款原因
            record.setRefundReason(params.get("refundReason"));
            
            // 退款详情
            if (refundResponse.containsKey("refund_detail_item_list")) {
                JSONArray refundDetailList = refundResponse.getJSONArray("refund_detail_item_list");
                if (refundDetailList != null) {
                    record.setRefundDetail(JSON.toJSONString(refundDetailList));
                }
            }
            
            // 用户收到退款账户
            record.setUserReceivedAccount(refundResponse.getString("buyer_logon_id"));
            
            // 退款时间
            String gmtRefundPayStr = refundResponse.getString("gmt_refund_pay");
            if (StringUtils.isNotBlank(gmtRefundPayStr)) {
                try {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date refundTime = sdf.parse(gmtRefundPayStr);
                    record.setRefundSuccessTime(refundTime);
                    record.setRefundCreateTime(refundTime); // 支付宝没有单独的创建时间
                } catch (ParseException e) {
                    log.warn("解析退款时间失败: {}", gmtRefundPayStr, e);
                }
            }
            
            // 业务信息（从params获取，如果有的话）
            if (params.containsKey("userId")) {
                try {
                    record.setUserId(Integer.parseInt(params.get("userId")));
                } catch (NumberFormatException e) {
                    log.warn("解析userId失败: {}", params.get("userId"));
                }
            }
            if (params.containsKey("orderId")) {
                record.setOrderId(params.get("orderId"));
            }
            if (params.containsKey("storeId")) {
                try {
                    record.setStoreId(Integer.parseInt(params.get("storeId")));
                } catch (NumberFormatException e) {
                    log.warn("解析storeId失败: {}", params.get("storeId"));
                }
            }
            
            // 响应数据
            record.setResponseData(responseBody.toJSONString());
            
            // 标准字段
            record.setDeleteFlag(0);
            record.setCreatedTime(new Date());
            
            return record;
        } catch (Exception e) {
            log.error("构建RefundRecord对象失败", e);
            return null;
        }
    }

    /**
     * 从支付宝退款错误响应构建RefundRecord对象（失败情况）
     */
    private RefundRecord buildRefundRecordFromAlipayError(JSONObject refundResponse, JSONObject responseBody, Map<String, String> params) {
        try {
            RefundRecord record = new RefundRecord();
            
            // 基本信息
            record.setPayType(PaymentEnum.ALIPAY.getType());
            record.setOutTradeNo(params.get("outTradeNo"));
            // 部分退款编号作为商户退款单号，如果没有则生成一个
            String outRefundNo = params.get("partialRefundCode");
            if (StringUtils.isBlank(outRefundNo)) {
                outRefundNo = UniqueRandomNumGenerator.generateUniqueCode(19);
            }
            record.setOutRefundNo(outRefundNo);
            record.setRefundStatus("ABNORMAL");
            
            // 金额信息
            String refundAmountStr = params.get("refundAmount");
            if (StringUtils.isNotBlank(refundAmountStr)) {
                record.setRefundAmount(new BigDecimal(refundAmountStr).multiply(new BigDecimal(100)).longValue());
            }
            String totalAmountStr = params.get("totalAmount");
            if (StringUtils.isNotBlank(totalAmountStr)) {
                record.setTotalAmount(new BigDecimal(totalAmountStr).multiply(new BigDecimal(100)).longValue());
            }
            record.setCurrency("CNY");
            
            // 退款原因
            record.setRefundReason(params.get("refundReason"));
            
            // 错误信息
            record.setErrorCode(refundResponse.getString("code"));
            record.setErrorMsg(refundResponse.getString("sub_msg"));
            
            // 业务信息
            if (params.containsKey("userId")) {
                try {
                    record.setUserId(Integer.parseInt(params.get("userId")));
                } catch (NumberFormatException e) {
                    log.warn("解析userId失败: {}", params.get("userId"));
                }
            }
            if (params.containsKey("orderId")) {
                record.setOrderId(params.get("orderId"));
            }
            if (params.containsKey("storeId")) {
                try {
                    record.setStoreId(Integer.parseInt(params.get("storeId")));
                } catch (NumberFormatException e) {
                    log.warn("解析storeId失败: {}", params.get("storeId"));
                }
            }
            
            // 响应数据
            record.setResponseData(responseBody.toJSONString());
            
            // 标准字段
            record.setDeleteFlag(0);
            record.setCreatedTime(new Date());
            record.setRefundCreateTime(new Date());
            
            return record;
        } catch (Exception e) {
            log.error("构建RefundRecord对象失败", e);
            return null;
        }
    }

}

