import enum
from datetime import datetime

from sqlalchemy import BigInteger, Boolean, DateTime, ForeignKey, Integer, String, Text
from sqlalchemy import Enum as SAEnum
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.types import JSON

from app.models.base import BaseModel


class OrderStatus(str, enum.Enum):
    PENDING = "pending"       # 待支付（预留，目前余额直接扣）
    PAID = "paid"             # 已支付
    CANCELLED = "cancelled"   # 已取消
    REFUNDED = "refunded"     # 已退款


class Order(BaseModel):
    """服务订单。用户从购物车结算后生成，记录购买快照和支付状态。"""

    __tablename__ = "orders"

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

    # 业务单号，格式：ORD{timestamp}{random6}
    out_order_no: Mapped[str] = mapped_column(String(64), unique=True, nullable=False, index=True)

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

    # 金额，单位分
    total_amount: Mapped[int] = mapped_column(Integer, nullable=False, comment="订单总金额，单位分")
    discount_amount: Mapped[int] = mapped_column(Integer, default=0, nullable=False, comment="优惠金额，单位分")

    promo_code_id: Mapped[int | None] = mapped_column(
        ForeignKey("promo_codes.id", ondelete="SET NULL"), nullable=True
    )

    # 下单时的购物车快照，防止产品改价后对不上账
    items_snapshot: Mapped[list | None] = mapped_column(JSON, nullable=True, comment="购物车项快照")

    remark: Mapped[str | None] = mapped_column(Text, nullable=True)

    # ── 代理/会员结算快照字段 ──
    agent_id: Mapped[int | None] = mapped_column(
        BigInteger, nullable=True, index=True, comment="关联代理用户ID",
    )
    agent_tier_id: Mapped[int | None] = mapped_column(
        Integer, nullable=True, comment="代理档位ID快照",
    )
    agent_cost_rate: Mapped[int | None] = mapped_column(
        Integer, nullable=True, comment="代理成本折扣率，万分比",
    )
    agent_cost_amount: Mapped[int | None] = mapped_column(
        Integer, nullable=True, comment="代理成本金额，单位分",
    )
    agent_delta_amount: Mapped[int | None] = mapped_column(
        Integer, nullable=True, comment="代理差额：正=收益，负=补贴",
    )
    member_commission_rate: Mapped[int | None] = mapped_column(
        Integer, nullable=True, comment="会员返佣比例快照，万分比",
    )
    member_commission_amount: Mapped[int | None] = mapped_column(
        Integer, nullable=True, comment="会员返佣金额快照，单位分",
    )
    settlement_status: Mapped[str | None] = mapped_column(
        String(24), default="pending", nullable=True, index=True,
        comment="结算状态: pending / settled / partial / reversed",
    )
    aff_code: Mapped[str | None] = mapped_column(
        String(64), nullable=True, comment="归因AFF代码",
    )
    points_claimed: Mapped[bool] = mapped_column(
        Boolean, default=False, nullable=False, comment="是否已领取该订单的自购返积分",
    )
    points_claimed_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), nullable=True, comment="首次领取自购返积分时间",
    )
    points_claimed_amount: Mapped[int] = mapped_column(
        Integer, default=0, nullable=False, comment="已领取自购返积分数量",
    )
