"""
支付业务服务

职责：Alipay SDK 封装、创建订单、处理支付通知、查询状态
遵循 BACKEND_DEV.md "薄路由 + 厚服务" 原则
"""
from datetime import datetime, timezone, timedelta
import uuid

from alipay import AliPay
from loguru import logger

from app.core.config import settings
from app.core.security import decode_payment_token
from app.repositories.orders import create_order, get_order_by_trade_no, update_order_status
from app.repositories.users import update_user

# 支付宝网关地址
ALIPAY_GATEWAY = "https://openapi.alipay.com/gateway.do"
ALIPAY_GATEWAY_SANDBOX = "https://openapi-sandbox.dl.alipaydev.com/gateway.do"


def _get_alipay_client() -> AliPay:
    """延迟初始化 Alipay 客户端"""
    return AliPay(
        appid=settings.ALIPAY_APP_ID,
        app_notify_url=settings.ALIPAY_NOTIFY_URL,
        app_private_key_string=open(settings.ALIPAY_PRIVATE_KEY_PATH).read(),
        alipay_public_key_string=open(settings.ALIPAY_PUBLIC_KEY_PATH).read(),
        sign_type="RSA2",
        debug=settings.ALIPAY_SANDBOX,
    )


def _create_page_pay_url(out_trade_no: str, amount: float, subject: str) -> str | None:
    """调用 alipay.trade.page.pay，返回支付宝收银台 URL"""
    client = _get_alipay_client()
    order_string = client.api_alipay_trade_page_pay(
        subject=subject,
        out_trade_no=out_trade_no,
        total_amount=amount,
        return_url=settings.ALIPAY_RETURN_URL,
    )
    if not order_string:
        logger.error(f"电脑网站支付下单失败: {out_trade_no}")
        return None

    gateway = ALIPAY_GATEWAY_SANDBOX if settings.ALIPAY_SANDBOX else ALIPAY_GATEWAY
    pay_url = f"{gateway}?{order_string}"
    logger.info(f"电脑网站支付下单成功: {out_trade_no}")
    return pay_url


def _verify_signature(data: dict, signature: str) -> bool:
    """验证支付宝异步通知签名"""
    client = _get_alipay_client()
    return client.verify(data, signature)


def create_payment_order(payment_token: str) -> dict:
    """
    创建支付订单完整流程

    Returns: {"pay_url": str, "out_trade_no": str, "amount": float}
    Raises: ValueError (token 无效), RuntimeError (API 失败)
    """
    user_id = decode_payment_token(payment_token)
    if not user_id:
        raise ValueError("付费凭证无效或已过期，请重新登录")

    out_trade_no = f"VG_{int(datetime.now().timestamp())}_{uuid.uuid4().hex[:8]}"
    amount = settings.PAYMENT_AMOUNT

    create_order(user_id, out_trade_no, amount)

    pay_url = _create_page_pay_url(out_trade_no, amount, "IPAgent 会员开通")
    if not pay_url:
        raise RuntimeError("创建支付订单失败，请稍后重试")

    logger.info(f"用户 {user_id} 创建支付订单: {out_trade_no}")

    return {"pay_url": pay_url, "out_trade_no": out_trade_no, "amount": amount}


def handle_payment_notify(form_data: dict) -> bool:
    """
    处理支付宝异步通知完整流程

    Returns: True=验签通过, False=验签失败
    """
    data = dict(form_data)

    signature = data.pop("sign", "")
    data.pop("sign_type", None)

    if not _verify_signature(data, signature):
        logger.warning(f"支付宝通知验签失败: {data.get('out_trade_no')}")
        return False

    out_trade_no = data.get("out_trade_no", "")
    trade_status = data.get("trade_status", "")
    trade_no = data.get("trade_no", "")

    logger.info(f"收到支付宝通知: {out_trade_no}, status={trade_status}, trade_no={trade_no}")

    if trade_status not in ("TRADE_SUCCESS", "TRADE_FINISHED"):
        return True

    order = get_order_by_trade_no(out_trade_no)
    if not order:
        logger.warning(f"订单不存在: {out_trade_no}")
        return True

    if order["status"] == "paid":
        logger.info(f"订单已处理过: {out_trade_no}")
        return True

    update_order_status(out_trade_no, "paid", trade_no)

    user_id = order["user_id"]
    expires_at = (datetime.now(timezone.utc) + timedelta(days=settings.PAYMENT_EXPIRE_DAYS)).isoformat()
    update_user(user_id, {
        "is_active": True,
        "role": "user",
        "expires_at": expires_at,
    })

    logger.success(f"用户 {user_id} 支付成功，已激活，有效期至 {expires_at}")
    return True


def get_order_status(out_trade_no: str) -> str | None:
    """查询订单支付状态"""
    order = get_order_by_trade_no(out_trade_no)
    if not order:
        return None
    return order["status"]
