"""Claimable point rewards generated by paid service events."""
from datetime import datetime
import enum

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

from app.models.base import BaseModel


class PointRewardStatus(str, enum.Enum):
    PENDING = "pending"
    CLAIMABLE = "claimable"
    CLAIMED = "claimed"
    CANCELLED = "cancelled"
    REVERSED = "reversed"


class PointReward(BaseModel):
    """Self-purchase reward points that must be claimed before becoming usable."""

    __tablename__ = "point_rewards"

    user_id: Mapped[int] = mapped_column(
        BigInteger, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True
    )
    order_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("orders.id", ondelete="CASCADE"), nullable=False, index=True
    )
    instance_id: Mapped[int | None] = mapped_column(
        Integer, ForeignKey("instances.id", ondelete="SET NULL"), nullable=True, index=True
    )
    source_type: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
    status: Mapped[str] = mapped_column(
        String(24), default=PointRewardStatus.PENDING.value, nullable=False, index=True
    )
    amount_cents: Mapped[int] = mapped_column(Integer, nullable=False, comment="Reward base amount in cents")
    reward_rate: Mapped[int] = mapped_column(Integer, nullable=False, comment="Reward rate in basis points")
    points: Mapped[int] = mapped_column(Integer, nullable=False, comment="Reward points")
    ref_no: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
    point_log_id: Mapped[int | None] = mapped_column(
        Integer, ForeignKey("point_logs.id", ondelete="SET NULL"), nullable=True
    )
    reverse_point_log_id: Mapped[int | None] = mapped_column(
        Integer, ForeignKey("point_logs.id", ondelete="SET NULL"), nullable=True
    )
    claimed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    cancelled_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    reversed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    remark: Mapped[str | None] = mapped_column(Text, nullable=True)
    payload_snapshot: Mapped[dict | None] = mapped_column(JSON, nullable=True)
