"""会员等级 & 积分流水模型"""
from decimal import Decimal
from datetime import datetime

from sqlalchemy import BigInteger, DECIMAL, ForeignKey, Index, Integer, String, Text, UniqueConstraint
from sqlalchemy.dialects.mysql import DATETIME as MYSQL_DATETIME, TINYINT
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.core.models.base import Base, TenantMixin, TimestampMixin


class MemberLevel(Base, TenantMixin, TimestampMixin):
    """会员等级配置"""

    __tablename__ = "member_levels"
    __table_args__ = (
        UniqueConstraint("tenant_id", "code", name="uk_member_levels_tenant_code"),
        Index("ix_member_levels_rank", "tenant_id", "rank"),
        Index("ix_member_levels_active", "is_active"),
        {
            "mysql_engine": "InnoDB",
            "mysql_charset": "utf8mb4",
            "mysql_collate": "utf8mb4_unicode_ci",
        },
    )

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    name: Mapped[str] = mapped_column(String(80), nullable=False)
    code: Mapped[str] = mapped_column(String(50), nullable=False)
    rank: Mapped[int] = mapped_column(Integer, nullable=False, default=0, comment="等级排序，越大等级越高")
    discount_rate: Mapped[Decimal] = mapped_column(DECIMAL(5, 4), nullable=False, default=Decimal("1.0000"))
    points_multiplier: Mapped[Decimal] = mapped_column(DECIMAL(8, 4), nullable=False, default=Decimal("1.0000"))
    free_shipping_threshold: Mapped[Decimal | None] = mapped_column(DECIMAL(12, 2), nullable=True)
    upgrade_spend: Mapped[Decimal | None] = mapped_column(DECIMAL(12, 2), nullable=True)
    upgrade_orders: Mapped[int | None] = mapped_column(Integer, nullable=True)
    validity_days: Mapped[int | None] = mapped_column(Integer, nullable=True)
    is_active: Mapped[int] = mapped_column(TINYINT(1), nullable=False, default=1)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)

    customers = relationship("Customer", back_populates="member_level", lazy="noload")

    def __init__(self, **kwargs):
        kwargs.setdefault("rank", 0)
        kwargs.setdefault("discount_rate", Decimal("1.0000"))
        kwargs.setdefault("points_multiplier", Decimal("1.0000"))
        kwargs.setdefault("is_active", 1)
        super().__init__(**kwargs)

    def __repr__(self) -> str:
        return f"<MemberLevel id={self.id} code={self.code!r}>"


class MemberPointsLedger(Base, TenantMixin, TimestampMixin):
    """会员积分流水"""

    __tablename__ = "member_points_ledger"
    __table_args__ = (
        Index("ix_points_customer", "customer_id", "created_at"),
        Index("ix_points_order", "order_id"),
        {
            "mysql_engine": "InnoDB",
            "mysql_charset": "utf8mb4",
            "mysql_collate": "utf8mb4_unicode_ci",
        },
    )

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    customer_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("customers.id", ondelete="CASCADE"), nullable=False)
    order_id: Mapped[int | None] = mapped_column(BigInteger, ForeignKey("orders.id", ondelete="SET NULL"), nullable=True)
    change_amount: Mapped[int] = mapped_column(Integer, nullable=False, comment="本次积分变动（正为获得，负为消耗）")
    balance_after: Mapped[int] = mapped_column(Integer, nullable=False, comment="变动后余额")
    reason: Mapped[str] = mapped_column(String(80), nullable=False, comment="变动原因")
    note: Mapped[str | None] = mapped_column(String(255), nullable=True)
    expires_at: Mapped[datetime | None] = mapped_column(MYSQL_DATETIME(fsp=3), nullable=True)

    customer = relationship("Customer", lazy="noload")
