/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.api.controller;

import com.yami.shop.bean.app.param.PayParam;
import com.yami.shop.bean.pay.PayInfoDto;
import com.yami.shop.security.api.model.YamiUser;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.PayService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import com.yami.shop.common.response.ServerResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 支付相关的接口控制器类，主要负责处理订单支付相关的操作，向外提供了支付接口以及普通支付接口，
 * 通过调用PayService的相关方法完成支付业务逻辑，并根据业务结果返回相应的响应信息给客户端。
 *
 * @author lanhai
 */
@RestController
// 设置该控制器类对应的请求映射路径，后续类中的接口方法路径会基于此进行拼接，这里表明是与订单支付相关的接口所在的基础路径。
@RequestMapping("/p/order")
// 使用 @Tag 注解为该控制器类添加标签说明，用于在 API 文档（如 Swagger 生成的文档）中对该类下的接口进行分类展示，这里表明是“订单接口”相关的一组接口。
@Tag(name = "订单接口")
// 通过Lombok的 @AllArgsConstructor 注解生成包含所有参数的构造函数，用于依赖注入PayService实例，方便后续调用支付相关的业务方法。
@AllArgsConstructor
public class PayController {

    // 注入PayService，用于处理与支付相关的核心业务逻辑，例如发起支付、处理支付成功后的业务逻辑等操作。
    private final PayService payService;

    /**
     * 支付接口方法，用于根据传入的支付参数（PayParam对象）进行订单支付操作，并返回相应的响应结果给客户端。
     * 通过 @PostMapping 注解将该方法映射到 HTTP 的 POST 请求方式，请求路径为“/pay”，意味着客户端需要通过发送POST请求到该路径来调用此支付接口。
     * @Operation 注解用于在 API 文档中对该接口进行详细描述，这里的摘要（summary）和详细描述（description）都表明是根据订单号进行支付的功能，方便接口使用者了解接口用途。
     *
     * @param payParam 包含支付相关参数的请求体对象，例如订单号、支付方式等信息，具体字段取决于PayParam类的定义，这些参数将用于支付业务逻辑的处理。
     * @return 返回一个表示操作成功的ServerResponseEntity对象，由于这里主要是执行支付操作，没有需要返回的具体业务数据，所以返回的是Void类型的成功响应，告知客户端支付请求已受理并处理。
     */
    @PostMapping("/pay")
    @Operation(summary = "根据订单号进行支付", description = "根据订单号进行支付")
    public ServerResponseEntity<Void> pay(@RequestBody PayParam payParam) {
        // 通过SecurityUtils工具类获取当前登录用户信息，封装在YamiUser对象中，后续可能用于验证用户身份、关联支付记录与用户等操作。
        YamiUser user = SecurityUtils.getUser();
        // 从获取到的用户对象中提取用户ID，作为支付操作中关联用户的关键标识，传递给后续的支付业务逻辑处理方法。
        String userId = user.getUserId();

        // 调用PayService的pay方法，传入用户ID和支付参数，发起支付操作，该方法会根据传入的参数进行具体的支付流程处理，
        // 例如与支付平台交互、生成支付订单等，并返回包含支付相关信息的PayInfoDto对象，如支付单号等信息。
        PayInfoDto payInfo = payService.pay(userId, payParam);
        // 调用PayService的paySuccess方法，传入支付单号等信息，用于处理支付成功后的相关业务逻辑，比如更新订单状态、记录支付记录等操作，
        // 第二个参数为空字符串，可能表示一些额外的备注信息等，具体含义取决于paySuccess方法的实现逻辑。
        payService.paySuccess(payInfo.getPayNo(), "");
        return ServerResponseEntity.success();
    }

    /**
     * 普通支付接口方法，功能与上述的支付接口类似，也是根据传入的支付参数（PayParam对象）进行订单支付操作，
     * 但在返回结果上有所不同，这里返回一个包含布尔值的ServerResponseEntity对象，用于表示支付操作是否成功（目前直接返回true）。
     * 通过 @PostMapping 注解将该方法映射到 HTTP 的 POST 请求方式，请求路径为“/normalPay”，客户端通过该路径发送POST请求来调用此接口。
     * @Operation 注解同样用于在 API 文档中对该接口进行描述，表明是根据订单号进行支付的功能。
     *
     * @param payParam 包含支付相关参数的请求体对象，例如订单号、支付方式等信息，具体字段取决于PayParam类的定义，这些参数将用于支付业务逻辑的处理。
     * @return 返回一个包含表示操作成功的布尔值的ServerResponseEntity对象，目前总是返回true，表示支付操作在业务逻辑层面被视为成功，具体的实际支付结果可能需要结合后续的业务逻辑以及支付平台反馈等综合判断。
     */
    @PostMapping("/normalPay")
    @Operation(summary = "根据订单号进行支付", description = "根据订单号进行支付")
    public ServerResponseEntity<Boolean> normalPay(@RequestBody PayParam payParam) {

        YamiUser user = SecurityUtils.getUser();
        String userId = user.getUserId();
        PayInfoDto pay = payService.pay(userId, payParam);

        // 根据内部订单号更新order settlement，调用PayService的paySuccess方法处理支付成功后的业务逻辑，传入支付单号等信息，
        // 这里的操作与上面的支付接口中的paySuccess调用类似，都是为了保证支付成功后相关业务数据的更新和一致性。
        payService.paySuccess(pay.getPayNo(), "");

        return ServerResponseEntity.success(true);
    }
}