package com.jeesharp.business.modules.finance.api;

import com.jeesharp.business.modules.finance.payorder.dto.PayOrderPrepayRouteDTO;
import com.jeesharp.business.modules.finance.payorder.vo.PayOrderInfoVO;
import com.jeesharp.business.modules.finance.payorder.vo.PayOrderIntentVO;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 财务支付单跨模块 API：C 端 JSAPI 意图、预支付回写、微信回调落成功态及只读查询。
 *
 * <p>垂直域 Application / mobile-gateway 仅依赖本接口，勿直接依赖 {@code PayOrderApplicationService}。
 * 实现类见 {@code PayOrderApiImpl}。</p>
 *
 * <p>典型调用链：</p>
 * <pre>
 * 预支付：createIntentForJsapi → 微信统一下单 → bindPrepayAfterJsapi
 * 回调：微信 notify → markPaidByPayOrderId / markPaidByWechatOutTradeNo
 * </pre>
 *
 * @author jeesharp
 * @since 2026-06-09
 */
public interface PayOrderApi {

    /**
     * 按主键查询支付单详情。
     *
     * @param id 财务支付单主键 {@code biz_pay_order.id}
     * @return 支付单详情；不存在时由实现层返回 null 或抛业务异常（以实现为准）
     */
    PayOrderInfoVO get(String id);

    /**
     * 创建 JSAPI 支付意图（最简入参）。
     *
     * @param bizScene   业务场景编码，见 {@link com.jeesharp.business.modules.finance.paymentrecord.enums.PayRecordBizSceneEnum}
     * @param bizOrderId 业务订单/预约单主键
     * @param amountYuan 应付金额（元）
     * @param memberId   下单会员 ID，可空
     * @param subject    支付标题（微信 description / 对账展示）
     * @return payOrderId、out_trade_no、tenantId，供统一下单与 attach 回传
     */
    PayOrderIntentVO createIntentForJsapi(String bizScene, String bizOrderId, BigDecimal amountYuan,
            String memberId, String subject);

    /**
     * 创建 JSAPI 支付意图（含预支付所需扩展字段）。
     *
     * @param description   商品描述，可空则回退 subject
     * @param notifyUrl     微信异步通知地址，可空则走平台默认回调
     * @param channelUserId 微信 openid（JSAPI 必填）
     * @param userIp        客户端 IP，风控/渠道要求时使用
     */
    PayOrderIntentVO createIntentForJsapi(String bizScene, String bizOrderId, BigDecimal amountYuan,
            String memberId, String subject, String description, String notifyUrl, String channelUserId,
            String userIp);

    /**
     * 创建 JSAPI 支付意图（含租户 ID，多租户支付配置隔离）。
     *
     * @param tenantId 平台租户 ID，决定微信商户号/证书等配置
     */
    PayOrderIntentVO createIntentForJsapi(String bizScene, String bizOrderId, BigDecimal amountYuan,
            String memberId, String subject, String description, String notifyUrl, String channelUserId,
            String userIp, String tenantId);

    /**
     * 创建 JSAPI 支付意图（含结算模式与分账标记）。
     *
     * @param settleMode         结算模式，见 {@link com.jeesharp.business.modules.finance.merchantsettle.enums.SettleModeEnum}；空则默认平台代收
     * @param needProfitSharing  是否需微信分账：true 时在支付单上标记 need_profit_sharing=1
     */
    PayOrderIntentVO createIntentForJsapi(String bizScene, String bizOrderId, BigDecimal amountYuan,
            String memberId, String subject, String description, String notifyUrl, String channelUserId,
            String userIp, String tenantId, String settleMode, Boolean needProfitSharing);

    /**
     * 创建 JSAPI 支付意图（完整参数，含收付通路由）。
     * <p>各业态预支付入口推荐调用此重载，以便写入直连/服务商/合单路由及子商户号。</p>
     *
     * @param route 收付通预支付路由：payRouteType（DIRECT/PARTNER/COMBINE）、subMchId、combineOutTradeNo 等
     */
    PayOrderIntentVO createIntentForJsapi(String bizScene, String bizOrderId, BigDecimal amountYuan,
            String memberId, String subject, String description, String notifyUrl, String channelUserId,
            String userIp, String tenantId, String settleMode, Boolean needProfitSharing,
            PayOrderPrepayRouteDTO route);

    /**
     * 微信统一下单成功后回写 prepay_id，支付单状态 INIT → PREPAY_CREATED。
     *
     * @param payOrderId        财务支付单主键（createIntentForJsapi 返回）
     * @param prepayIdOrPackage prepay_id 或 {@code prepay_id=xxx} 格式字符串
     */
    void bindPrepayAfterJsapi(String payOrderId, String prepayIdOrPackage);

    /**
     * 微信回调成功：按商户 out_trade_no 将支付单置为 SUCCESS。
     * <p>兼容直连单号；合单场景也可传 combine_out_trade_no。幂等，重复回调不重复更新。</p>
     *
     * @param outTradeNo         商户订单号（统一下单时的 out_trade_no）
     * @param thirdPartyTradeNo  微信支付流水号 transaction_id
     * @param amountYuan         实付金额（元），可空则保留原 intent 金额
     * @param payTime            支付完成时间，可空则取当前时间
     */
    void markPaidByWechatOutTradeNo(String outTradeNo, String thirdPartyTradeNo, BigDecimal amountYuan,
            LocalDateTime payTime);

    /**
     * 微信回调成功：按 attach.payOrderId 精确定位支付单并置为 SUCCESS（新链路首选）。
     * <p>预下单 attach 携带 payOrderId 时优先调用本方法，避免 out_trade_no 歧义。</p>
     *
     * @param payOrderId         财务支付单主键
     * @param thirdPartyTradeNo  微信支付流水号 transaction_id
     * @param amountYuan         实付金额（元）
     * @param payTime            支付完成时间
     */
    void markPaidByPayOrderId(String payOrderId, String thirdPartyTradeNo, BigDecimal amountYuan,
            LocalDateTime payTime);
}
