package shop.alien.store.strategy.platformMembershipPayment.impl;

import com.alibaba.fastjson.JSON;
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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import shop.alien.entity.result.R;
import shop.alien.entity.store.PlatformShopMembershipOrder;
import shop.alien.entity.store.PlatformShopMembershipPaymentOrder;
import shop.alien.store.service.PlatformShopMembershipOrderService;
import shop.alien.store.service.PlatformShopMembershipPaymentOrderService;
import shop.alien.store.strategy.platformMembershipPayment.PlatformMembershipPaymentStrategy;
import shop.alien.util.common.UniqueRandomNumGenerator;
import shop.alien.util.common.constant.PaymentEnum;
import shop.alien.util.system.OSUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 平台店铺会员卡 — 支付宝预支付/查单（支付流水写入 platform_shop_membership_payment_order）
 * <p>支付参数与 {@link shop.alien.store.strategy.payment.impl.AlipayPaymentStrategyImpl} 一致，从 payment.aliPay.business 读取，不读 store_payment_config。
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class PlatformMembershipAlipayPaymentStrategyImpl implements PlatformMembershipPaymentStrategy {

    @Value("${payment.aliPay.business.appId}")
    private String businessAppId;

    @Value("${payment.aliPay.business.appPrivateKey}")
    private String businessAppPrivateKey;

    @Value("${payment.aliPay.business.win.appCertPath}")
    private String businessWinAppCertPath;

    @Value("${payment.aliPay.business.win.alipayPublicCertPath}")
    private String businessWinAlipayPublicCertPath;

    @Value("${payment.aliPay.business.win.alipayRootCertPath}")
    private String businessWinAlipayRootCertPath;

    @Value("${payment.aliPay.business.linux.appCertPath}")
    private String businessLinuxAppCertPath;

    @Value("${payment.aliPay.business.linux.alipayPublicCertPath}")
    private String businessLinuxAlipayPublicCertPath;

    @Value("${payment.aliPay.business.linux.alipayRootCertPath}")
    private String businessLinuxAlipayRootCertPath;

    @Value("${payment.aliPay.host}")
    private String aliPayHost;

    private static final String REDIS_PREPAY_KEY_PREFIX = "platform:membership:alipay:prepay:order:";
    private static final long REDIS_PREPAY_EXPIRE_SECONDS = 15 * 60;
    private static final String REDIS_PREPAY_DEBOUNCE_KEY_PREFIX = "platform:membership:alipay:prepay:debounce:order:";
    private static final long REDIS_PREPAY_DEBOUNCE_SECONDS = 5;

    private final PlatformShopMembershipOrderService platformShopMembershipOrderService;
    private final PlatformShopMembershipPaymentOrderService membershipPaymentOrderService;
    private final StringRedisTemplate stringRedisTemplate;

    @Override
    public R<Map<String, Object>> createPrePay(Integer storeId, Integer membershipOrderId, String amountYuan, String subject, Integer userId) {
        if (storeId == null || membershipOrderId == null) {
            return R.fail("门店ID和会员卡订单ID不能为空");
        }
        if (StringUtils.isBlank(amountYuan)) {
            return R.fail("支付金额不能为空");
        }
        BigDecimal amountYuanBD;
        try {
            amountYuanBD = new BigDecimal(amountYuan).setScale(2, RoundingMode.HALF_UP);
        } catch (NumberFormatException e) {
            return R.fail("支付金额格式不正确");
        }
        if (amountYuanBD.compareTo(BigDecimal.ZERO) <= 0) {
            return R.fail("支付金额必须大于0");
        }
        if (StringUtils.isBlank(subject)) {
            return R.fail("订单描述不能为空");
        }
        PlatformShopMembershipOrder order = platformShopMembershipOrderService.getById(membershipOrderId);
        if (order == null) {
            return R.fail("会员卡订单不存在");
        }
        if (!order.getStoreId().equals(storeId)) {
            return R.fail("订单与门店不匹配");
        }
        if (order.getPayStatus() != null && order.getPayStatus() != PlatformShopMembershipOrder.PAY_STATUS_PENDING) {
            return R.fail("订单不可支付");
        }
        BigDecimal expect = order.getPayAmount() != null ? order.getPayAmount() : BigDecimal.ZERO;
        if (amountYuanBD.compareTo(expect.setScale(2, RoundingMode.HALF_UP)) != 0) {
            return R.fail("支付金额与订单金额不一致");
        }

        String redisKey = REDIS_PREPAY_KEY_PREFIX + membershipOrderId;
        String cached = stringRedisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isNotBlank(cached)) {
            try {
                @SuppressWarnings("unchecked")
                Map<String, Object> data = JSON.parseObject(cached, Map.class);
                if (data != null && !data.isEmpty()) {
                    log.info("会员卡支付宝预支付命中缓存，membershipOrderId={}", membershipOrderId);
                    return R.data(data);
                }
            } catch (Exception e) {
                log.warn("解析会员卡预支付缓存失败，将重新发起，membershipOrderId={}", membershipOrderId, e);
            }
        }

        String debounceKey = REDIS_PREPAY_DEBOUNCE_KEY_PREFIX + membershipOrderId;
        Boolean debounceSet = stringRedisTemplate.opsForValue().setIfAbsent(debounceKey, "1", REDIS_PREPAY_DEBOUNCE_SECONDS, TimeUnit.SECONDS);
        if (Boolean.FALSE.equals(debounceSet)) {
            return R.fail("请勿重复提交，请稍后再试");
        }

        int deleted = membershipPaymentOrderService.logicDeletePendingByMembershipOrderIdAndPayType(
                membershipOrderId, PaymentEnum.ALIPAY.getType());
        if (deleted > 0) {
            log.info("已逻辑删除该会员卡订单下支付宝支付单 {} 条，membershipOrderId={}", deleted, membershipOrderId);
        }

        String outTradeNo = UniqueRandomNumGenerator.generateUniqueCode(19);
        Date now = new Date();
        PlatformShopMembershipPaymentOrder paymentOrder = new PlatformShopMembershipPaymentOrder();
        paymentOrder.setPaymentNo(membershipPaymentOrderService.generatePaymentNo());
        paymentOrder.setMembershipOrderId(order.getId());
        paymentOrder.setOrderSn(order.getOrderSn());
        paymentOrder.setStoreId(storeId);
        paymentOrder.setPayType(PaymentEnum.ALIPAY.getType());
        paymentOrder.setOutTradeNo(outTradeNo);
        paymentOrder.setPayAmount(amountYuanBD);
        paymentOrder.setPayStatus(0);
        paymentOrder.setPayerUserId(userId);
        paymentOrder.setSubject(subject);
        paymentOrder.setCreatedTime(now);
        paymentOrder.setUpdatedTime(now);
        membershipPaymentOrderService.save(paymentOrder);

        try {
            AlipayConfig alipayConfig = buildBusinessAlipayConfig();
            AlipayClient client = new DefaultAlipayClient(alipayConfig);
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            model.setOutTradeNo(outTradeNo);
            model.setTotalAmount(amountYuanBD.toPlainString());
            model.setSubject(subject);
            model.setTimeoutExpress("15m");
            request.setBizModel(model);
            AlipayTradeAppPayResponse response = client.sdkExecute(request);
            String orderStr = response.isSuccess() ? response.getBody() : "";
            if (!response.isSuccess()) {
                return R.fail("预支付失败：" + response.getSubMsg());
            }
            Map<String, Object> data = new HashMap<>();
            data.put("orderStr", orderStr);
            data.put("outTradeNo", outTradeNo);
            data.put("orderSn", order.getOrderSn());
            data.put("orderId", order.getId());
            data.put("paymentNo", paymentOrder.getPaymentNo());
            stringRedisTemplate.opsForValue().set(redisKey, JSON.toJSONString(data), REDIS_PREPAY_EXPIRE_SECONDS, TimeUnit.SECONDS);
            log.info("会员卡支付宝预支付成功 storeId={}, orderSn={}, outTradeNo={}", storeId, order.getOrderSn(), outTradeNo);
            return R.data(data);
        } catch (AlipayApiException e) {
            log.error("会员卡支付宝预支付异常 storeId={}, membershipOrderId={}", storeId, membershipOrderId, e);
            return R.fail("预支付失败：" + e.getErrMsg());
        } catch (Exception e) {
            log.error("构建支付宝配置异常 storeId={}", storeId, e);
            return R.fail("预支付失败：" + e.getMessage());
        }
    }

    @Override
    public R<Object> queryPayStatus(Integer storeId, String outTradeNo) {
        if (storeId == null || StringUtils.isBlank(outTradeNo)) {
            return R.fail("门店ID和商户订单号不能为空");
        }
        PlatformShopMembershipPaymentOrder paymentOrder = membershipPaymentOrderService.getByOutTradeNo(outTradeNo);
        if (paymentOrder == null) {
            return R.fail("支付单不存在");
        }
        if (!storeId.equals(paymentOrder.getStoreId())) {
            return R.fail("支付单与门店不匹配");
        }
        PlatformShopMembershipOrder order = platformShopMembershipOrderService.getById(paymentOrder.getMembershipOrderId());
        if (order == null) {
            return R.fail("会员卡订单不存在");
        }
        if (order.getPayStatus() != null && order.getPayStatus() == PlatformShopMembershipOrder.PAY_STATUS_PAID) {
            return R.success("支付成功");
        }
        try {
            AlipayConfig alipayConfig = buildBusinessAlipayConfig();
            AlipayClient client = new DefaultAlipayClient(alipayConfig);
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", outTradeNo);
            request.setBizContent(bizContent.toJSONString());
            AlipayTradeQueryResponse response = client.certificateExecute(request);
            if (!response.isSuccess()) {
                return R.fail("查询失败：" + response.getSubMsg());
            }
            String tradeStatus = response.getTradeStatus();
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                Date now = new Date();
                paymentOrder.setPayStatus(1);
                paymentOrder.setTradeNo(response.getTradeNo());
                paymentOrder.setPayTime(now);
                paymentOrder.setUpdatedTime(now);
                membershipPaymentOrderService.updateById(paymentOrder);
                platformShopMembershipOrderService.applyPaySuccess(order.getId(), now, outTradeNo, response.getTradeNo(), PaymentEnum.ALIPAY.getType());
                return R.success("支付成功");
            }
            if ("TRADE_CLOSED".equals(tradeStatus)) {
                return R.fail("交易已关闭");
            }
            if ("WAIT_BUYER_PAY".equals(tradeStatus)) {
                return R.fail("等待买家付款");
            }
            return R.success("订单状态：" + tradeStatus);
        } catch (AlipayApiException e) {
            log.error("会员卡支付宝查单异常 outTradeNo={}", outTradeNo, e);
            return R.fail("查询异常：" + e.getErrMsg());
        } catch (Exception e) {
            log.error("会员卡支付宝查单异常 storeId={}", storeId, e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }

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

    @Override
    public R<String> refundForTest(PlatformShopMembershipPaymentOrder po, String refundAmountYuan, String refundReason) {
        if (po == null || StringUtils.isBlank(po.getOutTradeNo())) {
            return R.fail("支付单或商户订单号无效");
        }
        if (!PaymentEnum.ALIPAY.getType().equals(po.getPayType())) {
            return R.fail("非支付宝会员卡支付单");
        }
        if (StringUtils.isBlank(refundAmountYuan)) {
            return R.fail("退款金额不能为空");
        }
        BigDecimal refundBd;
        try {
            refundBd = new BigDecimal(refundAmountYuan).setScale(2, RoundingMode.HALF_UP);
        } catch (NumberFormatException e) {
            return R.fail("退款金额格式不正确");
        }
        if (refundBd.compareTo(BigDecimal.ZERO) <= 0) {
            return R.fail("退款金额必须大于0");
        }
        if (po.getPayAmount() != null
                && refundBd.compareTo(po.getPayAmount().setScale(2, RoundingMode.HALF_UP)) > 0) {
            return R.fail("退款金额不能超过原支付金额");
        }
        String outTradeNo = po.getOutTradeNo();
        try {
            AlipayConfig alipayConfig = buildBusinessAlipayConfig();
            AlipayClient client = new DefaultAlipayClient(alipayConfig);
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            model.setOutTradeNo(outTradeNo);
            model.setRefundAmount(refundBd.toPlainString());
            model.setRefundReason(StringUtils.isNotBlank(refundReason) ? refundReason : "测试退款");
            request.setBizModel(model);
            AlipayTradeRefundResponse response = client.certificateExecute(request);
            if (!response.isSuccess()) {
                return R.fail("退款失败：" + response.getSubMsg());
            }
            JSONObject body = JSONObject.parseObject(response.getBody());
            JSONObject refundResp = body != null ? body.getJSONObject("alipay_trade_refund_response") : null;
            String fundChange = refundResp != null ? refundResp.getString("fund_change") : null;
            String tradeNo = refundResp != null ? refundResp.getString("trade_no") : null;
            membershipPaymentOrderService.markPaymentAndMembershipOrderRefunded(po);
            log.warn("会员卡支付宝退款成功并已回写支付单/业务订单状态 membershipOrderId={}, outTradeNo={}, tradeNo={}, fundChange={}",
                    po.getMembershipOrderId(), outTradeNo, tradeNo, fundChange);
            return R.data("退款成功，已更新支付单与会员卡业务订单为已退款，membershipOrderId=" + po.getMembershipOrderId()
                    + ", trade_no=" + tradeNo + ", fund_change=" + fundChange);
        } catch (AlipayApiException e) {
            log.error("[测试]会员卡支付宝退款异常 outTradeNo={}", outTradeNo, e);
            return R.fail("退款异常：" + e.getErrMsg());
        } catch (Exception e) {
            log.error("[测试]会员卡支付宝退款异常 membershipOrderId={}", po.getMembershipOrderId(), e);
            return R.fail("退款失败：" + e.getMessage());
        }
    }

    private AlipayConfig buildBusinessAlipayConfig() {
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl(aliPayHost);
        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);
        }
        return alipayConfig;
    }
}
