"""按支付流水选择退款通道：付呗单走付呗，其余走原微信退款逻辑。"""
from __future__ import annotations

import logging
import random
import string
import time
from typing import Any, Dict, Optional

from jituan.constants import PAY_CHANNEL_FUBEI_WX_MINI
from jituan.services.club_payment_channel import get_fubei_config
from jituan.services import fubei_client
from jituan.services.mini_pay_router import get_pay_ledger

logger = logging.getLogger(__name__)


def _refund_sn(out_trade_no: str) -> str:
    ts = str(int(time.time()))
    rand = ''.join(random.choices('0123456789', k=4))
    # 付呗 merchant_refund_sn 最长 32
    base = f'{out_trade_no}R{ts}{rand}'
    return base[:32]


def try_fubei_refund(
    *,
    out_trade_no: str,
    amount_yuan,
    club_id: Optional[str] = None,
) -> Optional[Dict[str, Any]]:
    """
    若该单曾走付呗，则发起付呗退款并返回 {'code': 0/非0, 'msg': ..., 'refund_id': ...}；
    非付呗单返回 None，由调用方继续走原微信退款。
    """
    ledger = get_pay_ledger(out_trade_no)
    if not ledger or ledger.channel != PAY_CHANNEL_FUBEI_WX_MINI:
        return None

    cid = (club_id or ledger.club_id or '').strip()
    cfg = get_fubei_config(cid)
    if not cfg or not cfg.app_id or not cfg.api_key:
        logger.error('[FUBEI_REFUND] 配置缺失 club=%s out_trade_no=%s', cid, out_trade_no)
        return {'code': 500, 'msg': '付呗退款配置缺失，请检查俱乐部付呗通道'}

    merchant_refund_sn = _refund_sn(out_trade_no)
    try:
        data = fubei_client.refund_order(
            gateway_url=cfg.gateway_url,
            app_id=cfg.app_id,
            app_secret=cfg.api_key,
            merchant_order_sn=out_trade_no,
            merchant_refund_sn=merchant_refund_sn,
            refund_money=amount_yuan,
            order_sn=ledger.provider_order_sn or '',
        )
        refund_id = data.get('refund_sn') or merchant_refund_sn
        logger.info('[FUBEI_REFUND] ok out_trade_no=%s refund=%s', out_trade_no, refund_id)
        return {'code': 0, 'msg': 'success', 'refund_id': refund_id, 'raw': data}
    except Exception as exc:
        logger.error('[FUBEI_REFUND] fail out_trade_no=%s: %s', out_trade_no, exc, exc_info=True)
        return {'code': 400, 'msg': str(exc)}
