import enum

from sqlalchemy import BigInteger, ForeignKey, Integer, Numeric, String
from sqlalchemy import Enum as SAEnum
from sqlalchemy.orm import Mapped, mapped_column

from app.models.base import BaseModel


class RechargeStatus(str, enum.Enum):
    PENDING = "pending"       # 已创建，等待支付
    PAID = "paid"             # 支付成功，余额已到账
    EXPIRED = "expired"       # 超时未支付
    CLOSED = "closed"         # 主动关闭
    REFUNDED = "refunded"     # 已退款（预留）


class RechargeChannel(str, enum.Enum):
    ALIPAY = "alipay"
    WXPAY = "wxpay"
    QQPAY = "qqpay"
    ADMIN = "admin"           # 管理员手动充值


class RechargeOrder(BaseModel):
    """充值订单。每次用户发起充值生成一条记录，支付成功后更新余额并写 balance_logs。"""

    __tablename__ = "recharge_orders"

    user_id: Mapped[int] = mapped_column(
        BigInteger, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True
    )

    # 商户侧唯一订单号，格式：RC{timestamp}{random6}，用于对接易支付 out_trade_no
    out_trade_no: Mapped[str] = mapped_column(String(64), unique=True, nullable=False, index=True)

    # 易支付平台返回的订单号
    trade_no: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)

    # 支付插件 ID 与支付方式。余额入账仍由核心系统完成，插件不能直接改余额。
    payment_plugin: Mapped[str | None] = mapped_column(String(80), nullable=True, index=True)
    payment_method: Mapped[str | None] = mapped_column(String(32), nullable=True, index=True)
    notify_token: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)

    channel: Mapped[RechargeChannel] = mapped_column(
        SAEnum(RechargeChannel, values_callable=lambda e: [m.value for m in e]),
        nullable=False,
    )

    # 金额：元（两位小数），与易支付保持一致；到账后转 cents 写入 balance
    amount: Mapped[float] = mapped_column(Numeric(10, 2), nullable=False, comment="充值金额，单位元")
    amount_cents: Mapped[int] = mapped_column(Integer, nullable=False, comment="充值金额，单位分")

    status: Mapped[RechargeStatus] = mapped_column(
        SAEnum(RechargeStatus, values_callable=lambda e: [m.value for m in e]),
        default=RechargeStatus.PENDING,
        nullable=False,
        index=True,
    )

    # 易支付回调原始数据（JSON 字符串），便于排查
    callback_raw: Mapped[str | None] = mapped_column(String(2048), nullable=True)

    # 用户发起时的 IP
    client_ip: Mapped[str | None] = mapped_column(String(64), nullable=True)

    # 备注（管理员手动充值时填写）
    remark: Mapped[str | None] = mapped_column(String(255), nullable=True)
