"""付呗支付结果确认：主动查单（轮询/复查兜底，不依赖回调）。

规则：
- 流水表标明付呗 → 只查付呗（绝不误查微信直连）
- 无流水且俱乐部当前为付呗 → 先尝试付呗查单；查无单再回落微信
- 其它 → 返回 None，由调用方走微信/支付宝
"""
from __future__ import annotations

import logging
from typing import Any, Dict, Optional, Tuple

from jituan.constants import (
    CLUB_ID_DEFAULT,
    MINI_PAY_CHANNEL_FUBEI,
    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_club_mini_pay_channel, get_pay_ledger

logger = logging.getLogger(__name__)


def is_fubei_out_trade_no(out_trade_no: str) -> bool:
    ledger = get_pay_ledger(out_trade_no)
    return bool(ledger and ledger.channel == PAY_CHANNEL_FUBEI_WX_MINI)


def _should_try_fubei(out_trade_no: str, club_id: Optional[str]) -> Tuple[bool, str, str]:
    """
    返回 (是否应付呗查单, club_id, provider_order_sn)。
    有付呗流水 → 强制付呗；无流水但俱乐部选用付呗 → 尝试付呗。
    """
    cid = (club_id or '').strip() or CLUB_ID_DEFAULT
    ledger = get_pay_ledger(out_trade_no)
    if ledger and ledger.channel == PAY_CHANNEL_FUBEI_WX_MINI:
        return True, (ledger.club_id or cid), (ledger.provider_order_sn or '')
    if ledger:
        # 明确记了其它通道，不查付呗
        return False, cid, ''
    if get_club_mini_pay_channel(cid) == MINI_PAY_CHANNEL_FUBEI:
        return True, cid, ''
    return False, cid, ''


def query_fubei_trade(
    out_trade_no: str,
    club_id: Optional[str] = None,
) -> Optional[Dict[str, Any]]:
    """
    查询付呗订单。
    不应查付呗时返回 None；
    应查付呗时返回 data（含 trade_state）；查单业务失败时抛 Exception。
    """
    try_fb, cid, order_sn = _should_try_fubei(out_trade_no, club_id)
    if not try_fb:
        return None

    cfg = get_fubei_config(cid)
    if not cfg or not cfg.app_id or not cfg.api_key:
        # 俱乐部标了付呗但配置不齐：有流水则报错；仅「尝试」则回落微信
        ledger = get_pay_ledger(out_trade_no)
        if ledger and ledger.channel == PAY_CHANNEL_FUBEI_WX_MINI:
            logger.error('[FUBEI_QUERY] 配置缺失 club=%s out_trade_no=%s', cid, out_trade_no)
            raise Exception('付呗查单配置缺失')
        return None

    data = fubei_client.query_order(
        gateway_url=cfg.gateway_url,
        app_id=cfg.app_id,
        app_secret=cfg.api_key,
        merchant_order_sn=out_trade_no,
        order_sn=order_sn,
    )
    logger.info(
        '[FUBEI_QUERY] out_trade_no=%s club=%s trade_state=%s',
        out_trade_no, cid, data.get('trade_state'),
    )
    return data


def fubei_trade_is_success(data: Optional[Dict[str, Any]]) -> bool:
    if not data:
        return False
    state = str(data.get('trade_state') or '').upper()
    return state == 'SUCCESS'


def fubei_success_payload(
    out_trade_no: str,
    club_id: Optional[str] = None,
) -> Optional[Tuple[str, Any]]:
    """
    返回值约定（供复查/轮询统一使用）：
    - None：不是付呗单（或不应走付呗），调用方继续微信/支付宝
    - ('', None)：是付呗路径，但尚未支付成功（支付中）
    - (transaction_id, total_fee)：付呗已支付成功
    """
    try_fb, _, _ = _should_try_fubei(out_trade_no, club_id)
    if not try_fb:
        return None

    forced = is_fubei_out_trade_no(out_trade_no)
    try:
        data = query_fubei_trade(out_trade_no, club_id)
    except Exception as exc:
        msg = str(exc)
        logger.error('[FUBEI_QUERY] 查单异常 %s: %s', out_trade_no, exc, exc_info=True)
        # 无流水的「尝试」查询：订单不存在等可回落微信直连
        if not forced and any(k in msg for k in ('不存在', '无此', '未找到', 'ORDER', 'order')):
            return None
        # 有流水的付呗单：绝不能回落微信
        return ('', None)

    if data is None:
        return None if not forced else ('', None)

    if not fubei_trade_is_success(data):
        return ('', None)

    txn = str(
        data.get('trade_no')
        or data.get('platform_order_no')
        or data.get('order_sn')
        or out_trade_no
        or 'FUBEI_PAID'
    )
    total_fee = data.get('total_fee') or data.get('cash_fee') or data.get('order_price')
    return (txn, total_fee)
