package com.jeesharp.business.pay.notify;

import com.jeesharp.business.pay.adapter.MobilePayBizType;
import com.jeesharp.business.pay.service.WechatPayNotifyAdapterService;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 微信支付 V3 异步通知 HTTP 应答封装，与官方「验签通过后应答 200/204 无包体；失败应答 4xx/5xx + JSON」一致。
 *
 * @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012791861">支付成功回调通知（商户文档）</a>
 * @author jeesharp
 * @since 2026-05-26
 */
public final class WechatPayNotifyEntryControllerSupport {

    private WechatPayNotifyEntryControllerSupport() {
    }

    /**
     * 统一入口：从 attach.bizType 解析业态并路由（杏花村 C 端主链路）。
     */
    public static ResponseEntity<?> handleByAttach(Map<String, String> headers,
                                                 HttpServletRequest request,
                                                 WechatPayNotifyAdapterService service,
                                                 Logger log,
                                                 String logPrefix) {
        try {
            byte[] rawBytes = request.getInputStream().readAllBytes();
            String rawBody = rawBytes.length == 0 ? "" : new String(rawBytes, StandardCharsets.UTF_8);
            log.info("{} wechat notify inbound rawBodyBytesLength={}, headers={}, rawBody={}",
                logPrefix, rawBytes.length, headers, rawBody);
            service.handleNotifyByAttach(rawBody, headers);
            return ResponseEntity.noContent().build();
        } catch (SecurityException e) {
            log.error("{} wechat notify verify failed: {}", logPrefix, e.getMessage());
            return failBody(HttpStatus.INTERNAL_SERVER_ERROR, safeMessage(e.getMessage(), "验签失败"));
        } catch (IllegalArgumentException e) {
            log.warn("{} wechat notify bad request: {}", logPrefix, e.getMessage());
            return failBody(HttpStatus.BAD_REQUEST, safeMessage(e.getMessage(), "参数错误"));
        } catch (Exception e) {
            log.error("{} wechat notify error", logPrefix, e);
            return failBody(HttpStatus.INTERNAL_SERVER_ERROR, safeMessage(e.getMessage(), "处理失败"));
        }
    }

    /**
     * 按 URL 固定业态处理（遗留兼容；新代码请使用 {@link #handleByAttach}）。
     */
    public static ResponseEntity<?> handle(MobilePayBizType bizType,
                                           Map<String, String> headers,
                                           HttpServletRequest request,
                                           WechatPayNotifyAdapterService service,
                                           Logger log,
                                           String logPrefix) {
        try {
            byte[] rawBytes = request.getInputStream().readAllBytes();
            String rawBody = rawBytes.length == 0 ? "" : new String(rawBytes, StandardCharsets.UTF_8);
            log.info("{} wechat notify inbound rawBodyBytesLength={}, headers={}, rawBody={}",
                logPrefix, rawBytes.length, headers, rawBody);
            service.handleNotify(bizType, rawBody, headers);
            return ResponseEntity.noContent().build();
        } catch (SecurityException e) {
            log.error("{} wechat notify verify failed: {}", logPrefix, e.getMessage());
            return failBody(HttpStatus.INTERNAL_SERVER_ERROR, safeMessage(e.getMessage(), "验签失败"));
        } catch (IllegalArgumentException e) {
            log.warn("{} wechat notify bad request: {}", logPrefix, e.getMessage());
            return failBody(HttpStatus.BAD_REQUEST, safeMessage(e.getMessage(), "参数错误"));
        } catch (Exception e) {
            log.error("{} wechat notify error", logPrefix, e);
            return failBody(HttpStatus.INTERNAL_SERVER_ERROR, safeMessage(e.getMessage(), "处理失败"));
        }
    }

    private static String safeMessage(String message, String defaultMsg) {
        String m = message == null || message.isBlank() ? defaultMsg : message.trim();
        return m.length() > 256 ? m.substring(0, 256) : m;
    }

    /**
     * 应答失败：HTTP 4xx/5xx，body 为 {@code {"code":"FAIL","message":"..."}}（与官方失败应答示例一致）。
     */
    private static ResponseEntity<Map<String, String>> failBody(HttpStatus status, String message) {
        Map<String, String> body = new LinkedHashMap<>();
        body.put("code", "FAIL");
        body.put("message", message);
        return ResponseEntity.status(status).contentType(MediaType.APPLICATION_JSON).body(body);
    }
}
