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.constant.ResponseEnum;
import com.haha.common.enums.PaymentChannel;
import com.haha.common.utils.RequestParseUtil;
import com.haha.common.vo.Result;
import com.haha.service.payment.PaymentCallbackResult;
import com.haha.service.payment.PaymentResult;
import com.haha.service.payment.PaymentService;
import com.haha.service.payment.RefundResult;
import com.haha.service.payment.payscore.PayScoreCallbackResult;
import com.haha.service.payment.payscore.PayScoreService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * 统一支付控制器
 * 提供统一的支付API，支持多渠道支付（微信、支付宝等）
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/payment")
public class PaymentController {

    private final PaymentService paymentService;
    private final PayScoreService payScoreService;

    /**
     * 创建支付
     * POST /api/payment/create
     *
     * 请求参数:
     * - orderId: 订单ID（必填）
     * - channel: 支付渠道代码（必填，如 wechat/alipay/alipay_credit/balance）
     * - openId: 微信openId（微信支付必填）
     * - buyerId: 支付宝buyerId（支付宝支付必填）
     *
     * @param params 支付参数
     * @return 支付结果
     */
    @PostMapping("/create")
    public Result<PaymentResult> createPayment(@RequestBody Map<String, Object> params) {
        try {
            PaymentResult result = paymentService.createPayment(params);

            if (result.isSuccess()) {
                log.info("创建支付成功 - 订单ID: {}, 预支付ID: {}", params.get("orderId"), result.getPrepayId());
                return Result.success("创建支付成功", result);
            } else {
                log.warn("创建支付失败 - 订单ID: {}, 错误: {}", params.get("orderId"), result.getErrorMsg());
                return ResponseEnum.OPERATION_FAILED.toResult(result.getErrorMsg());
            }

        } catch (NumberFormatException e) {
            log.error("参数格式错误", e);
            return ResponseEnum.PARAM_FORMAT_ERROR.toResult("参数格式错误：orderId 必须为数字");
        } catch (Exception e) {
            log.error("创建支付失败", e);
            return ResponseEnum.OPERATION_FAILED.toResult("创建支付失败：" + e.getMessage());
        }
    }

    /**
     * 支付回调（按渠道路由）
     * POST /api/payment/callback/{channel}
     *
     * 注意：回调接口不需要 token 验证，使用 @SaIgnore
     *
     * @param channel       支付渠道代码
     * @param request       HTTP请求
     * @param requestParams 请求参数（form格式）
     * @return 回调响应
     */
    @SaIgnore
    @PostMapping("/callback/{channel}")
    public String handleCallback(
            @PathVariable String channel,
            HttpServletRequest request,
            @RequestParam(required = false) Map<String, String> requestParams) {
        try {
            log.info("收到支付回调 - 渠道: {}", channel);

            Map<String, Object> params;

            if (PaymentChannel.WECHAT_PAYSCORE.getCode().equalsIgnoreCase(channel)) {
                params = RequestParseUtil.parseWechatPayCallbackParams(request);

                PayScoreCallbackResult result = payScoreService.handlePayScoreCallback(params);

                if (result.isSuccess()) {
                    log.info("支付分回调处理成功 - outOrderNo: {}, eventType: {}, state: {}",
                            result.getOutOrderNo(), result.getEventType(), result.getState());
                    return CallbackConstants.WECHAT_PAYSCORE_SUCCESS;
                } else {
                    log.warn("支付分回调处理失败 - errorMsg: {}", result.getErrorMsg());
                    return CallbackConstants.WECHAT_PAYSCORE_FAIL;
                }
            }

            if (PaymentChannel.WECHAT.getCode().equalsIgnoreCase(channel)) {
                params = RequestParseUtil.parseWechatPayCallbackParams(request);

                String body = (String) params.get("body");
                if (body != null && !body.isEmpty()) {
                    try {
                        Map<String, Object> jsonParams = JSON.parseObject(body, Map.class);
                        params.putAll(jsonParams);
                    } catch (Exception ignored) {
                    }
                }
            } else {
                params = RequestParseUtil.parseRequestParams(request, requestParams);
            }
            log.info("支付回调参数: {}", JSON.toJSONString(params));

            PaymentChannel paymentChannel = PaymentChannel.fromCode(channel);
            if (paymentChannel == null) {
                log.warn("不支持的支付渠道: {}", channel);
                return buildCallbackErrorResponse(channel);
            }

            PaymentCallbackResult result = paymentService.handleCallback(paymentChannel, params);

            if (result.isSuccess()) {
                log.info("支付回调处理成功 - 订单号: {}, 交易号: {}", result.getOrderNo(), result.getTransactionId());
                return buildCallbackSuccessResponse(paymentChannel);
            } else {
                log.warn("支付回调处理失败 - 错误: {}", result.getErrorMsg());
                return buildCallbackErrorResponse(channel);
            }

        } catch (Exception e) {
            log.error("处理支付回调失败", e);
            return buildCallbackErrorResponse(channel);
        }
    }

    /**
     * 退款
     * POST /api/payment/refund
     *
     * 请求参数:
     * - orderId: 订单ID（必填）
     * - reason: 退款原因（可选）
     *
     * @param params 退款参数
     * @return 退款结果
     */
    /**
     * 退款申请
     * POST /api/payment/refund
     *
     * 用户提交退款申请，创建退款记录（PENDING），由管理员审核后执行。
     * 请求参数:
     * - orderId: 订单ID（必填）
     * - reason: 退款原因（可选）
     * - products: 退款商品列表（可选）
     * - refundAmount: 自定义退款金额（可选）
     */
    @PostMapping("/refund")
    public Result<RefundResult> refund(@RequestBody Map<String, Object> params) {
        try {
            RefundResult result = paymentService.refund(params);

            if (result.isSuccess()) {
                log.info("退款申请已提交 - 订单ID: {}, 退款单号: {}", params.get("orderId"), result.getRefundId());
                return Result.success("退款申请已提交，请等待审核", result);
            } else {
                log.warn("退款申请失败 - 订单ID: {}, 错误: {}", params.get("orderId"), result.getErrorMsg());
                return ResponseEnum.OPERATION_FAILED.toResult(result.getErrorMsg());
            }

        } catch (NumberFormatException e) {
            log.error("参数格式错误", e);
            return ResponseEnum.PARAM_FORMAT_ERROR.toResult("参数格式错误：orderId 必须为数字");
        } catch (Exception e) {
            log.error("退款申请失败", e);
            return ResponseEnum.OPERATION_FAILED.toResult("退款申请失败：" + e.getMessage());
        }
    }

    /**
     * 获取可用支付渠道
     * GET /api/payment/channels
     *
     * @return 支付渠道列表
     */
    @GetMapping("/channels")
    public Result<List<Map<String, String>>> getChannels() {
        try {
            List<Map<String, String>> channelList = paymentService.getChannelList();
            log.info("获取可用支付渠道 - 数量: {}", channelList.size());
            return Result.success("获取成功", channelList);

        } catch (Exception e) {
            log.error("获取支付渠道失败", e);
            return Result.error("获取支付渠道失败：" + e.getMessage());
        }
    }

    /**
     * 查询支付状态
     * GET /api/payment/query/{orderId}
     *
     * @param orderId 订单ID
     * @return 支付状态
     */
    @GetMapping("/query/{orderId}")
    public Result<PaymentResult> queryPayment(@PathVariable Long orderId) {
        try {
            log.info("查询支付状态 - 订单ID: {}", orderId);

            PaymentResult result = paymentService.queryPaymentStatus(orderId);

            if (result.isSuccess()) {
                return Result.success("查询成功", result);
            } else {
                return ResponseEnum.OPERATION_FAILED.toResult(result.getErrorMsg());
            }

        } catch (Exception e) {
            log.error("查询支付状态失败", e);
            return Result.error("查询支付状态失败：" + e.getMessage());
        }
    }

    /**
     * 构建回调成功响应
     * 根据不同支付渠道返回不同格式的成功响应
     *
     * @param channel 支付渠道
     * @return 成功响应
     */
    private String buildCallbackSuccessResponse(PaymentChannel channel) {
        if (channel == PaymentChannel.WECHAT) {
            return CallbackConstants.WECHAT_V3_SUCCESS;
        } else if (channel == PaymentChannel.ALIPAY || channel == PaymentChannel.ALIPAY_CREDIT) {
            return CallbackConstants.ALIPAY_SUCCESS;
        } else {
            return CallbackConstants.ALIPAY_SUCCESS;
        }
    }

    /**
     * 构建回调失败响应
     *
     * @param channelCode 支付渠道代码
     * @return 失败响应
     */
    private String buildCallbackErrorResponse(String channelCode) {
        if ("wechat".equalsIgnoreCase(channelCode)) {
            return CallbackConstants.WECHAT_V3_FAIL;
        } else {
            return CallbackConstants.FAIL;
        }
    }
}
