package com.haha.miniapp.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson2.JSON;
import com.haha.common.constant.CallbackConstants;
import com.haha.common.enums.NotifyType;
import com.haha.common.utils.RequestParseUtil;
import com.haha.service.HahaCallbackService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 哈哈平台回调通知接口
 *
 * 接收哈哈平台推送的各类通知，分为两类回调地址：
 *
 * 1. 消息回调地址 (/callback/haha/message)
 *    - DEVICE_STATUS: 开关门状态通知
 *    - ONLINE_STATUS: 设备在线状态通知
 *    - VOICE_RESULT: 音量调节结果通知
 *    - CLIENT_NEW_PRODUCT: 新品审核结果回调
 *    - MERGE_PRODUCT: 商品合并结果通知
 *    - ORC_RESULT: AI识别结果通知（最重要）
 *
 * 2. 订单回调地址 (/callback/haha/order)
 *    - 哈哈平台生成订单后推送的订单信息
 *    - 包含订单号、设备号、用户ID、订单明细、金额等
 *
 * 注意：
 * - 所有通知都包含 sign 字段用于验证
 * - 必须返回 "success" 字符串表示接收成功
 * - 未正确响应会触发重试机制
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/callback/haha")
@SaIgnore
public class CallbackController {

    private final HahaCallbackService hahaCallbackService;

    /**
     * 消息回调通知统一入口
     *
     * 接收哈哈平台推送的所有类型通知，通过 notify_type 区分具体类型
     * 支持 application/json 和 application/x-www-form-urlencoded 两种格式
     *
     * @param request HTTP请求对象
     * @param requestParams form表单参数（用于application/x-www-form-urlencoded）
     * @return 响应结果，必须返回 "success" 字符串
     */
    @PostMapping("/message")
    public String handleMessageCallback(HttpServletRequest request,
                                         @RequestParam(required = false) Map<String, String> requestParams) {
        try {
            Map<String, Object> params = RequestParseUtil.parseRequestParams(request, requestParams);
            String rawBody = readRawBodyIfFormUrlEncoded(request);

            log.info("收到消息回调通知: {}", JSON.toJSONString(params));

            String notifyType = (String) params.get("notify_type");
            if (notifyType == null || notifyType.isEmpty()) {
                log.warn("消息回调缺少 notify_type 参数");
                return CallbackConstants.HAHA_SUCCESS;
            }

            NotifyType type = NotifyType.fromCode(notifyType);
            if (type == null) {
                log.warn("未知的消息通知类型: {}", notifyType);
                return CallbackConstants.HAHA_SUCCESS;
            }

            hahaCallbackService.handleMessage(params, rawBody);

            return CallbackConstants.HAHA_SUCCESS;

        } catch (Exception e) {
            log.error("处理消息回调通知失败", e);
            return CallbackConstants.HAHA_SUCCESS;
        }
    }

    /**
     * 订单回调通知接口
     *
     * 当AI识别完成并生成订单后，哈哈平台会推送订单信息到此接口
     * 这是独立于消息回调的订单回调接口
     * 支持 application/json 和 application/x-www-form-urlencoded 两种格式
     *
     * @param request HTTP请求对象
     * @param requestParams form表单参数（用于application/x-www-form-urlencoded）
     * @return 响应结果，必须返回 "success" 字符串
     */
    @PostMapping("/order")
    public String handleOrderCallback(HttpServletRequest request,
                                       @RequestParam(required = false) Map<String, String> requestParams) {
        try {
            Map<String, Object> params = RequestParseUtil.parseRequestParams(request, requestParams);
            String rawBody = readRawBodyIfFormUrlEncoded(request);

            log.info("收到订单回调通知: {}", JSON.toJSONString(params));

            hahaCallbackService.handleOrderCallback(params, rawBody);

            return CallbackConstants.HAHA_SUCCESS;

        } catch (Exception e) {
            log.error("处理订单回调通知失败", e);
            return CallbackConstants.HAHA_SUCCESS;
        }
    }

    /**
     * 读取原始请求体（仅限 application/x-www-form-urlencoded 格式）
     * 用于签名验证时保留 PHP 端的原始 URL 编码
     */
    private String readRawBodyIfFormUrlEncoded(HttpServletRequest request) {
        String contentType = request.getContentType();
        if (contentType != null && contentType.toLowerCase().contains("application/x-www-form-urlencoded")) {
            return RequestParseUtil.readRequestBody(request);
        }
        return null;
    }

}
