from sqlalchemy import BigInteger, String, JSON, Integer, ForeignKey, Index
from sqlalchemy.dialects.mysql import TINYINT
from sqlalchemy.orm import Mapped, mapped_column
from app.core.models.base import Base, TimestampMixin, TenantMixin


class CarrierPackingRule(Base, TenantMixin, TimestampMixin):
    """物流渠道打包分箱规则（通用规则引擎条目）"""

    __tablename__ = "carrier_packing_rules"
    __table_args__ = (
        Index("ix_cpr_carrier_active", "carrier_id", "is_active"),
        Index("ix_cpr_tenant_carrier", "tenant_id", "carrier_id"),
        {
            "mysql_engine": "InnoDB",
            "mysql_charset": "utf8mb4",
            "mysql_collate": "utf8mb4_unicode_ci",
        },
    )

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    carrier_id: Mapped[int] = mapped_column(
        BigInteger,
        ForeignKey("shipping_carriers.id", ondelete="CASCADE"),
        nullable=False,
        comment="所属快递渠道 ID",
    )
    name: Mapped[str] = mapped_column(String(200), nullable=False, comment="规则名称（人类可读）")
    rule_type: Mapped[str] = mapped_column(
        String(30),
        nullable=False,
        comment="规则类型: LIMIT | UNIQUE | EXCLUSIVE | FORBIDDEN | INCOMPATIBLE | MIXED_LIMIT",
    )
    selector: Mapped[dict | None] = mapped_column(
        JSON,
        nullable=True,
        comment="商品选择器 {field, operator, value}；null 表示作用于整箱所有商品",
    )
    params: Mapped[dict] = mapped_column(
        JSON,
        nullable=False,
        default=dict,
        comment="规则参数，按 rule_type 不同含义不同",
    )
    message: Mapped[str | None] = mapped_column(
        String(500),
        nullable=True,
        comment="违规时返回的提示文案",
    )
    priority: Mapped[int] = mapped_column(
        Integer,
        nullable=False,
        default=0,
        comment="执行优先级，升序排列；FORBIDDEN 建议设 0，EXCLUSIVE 设 10，其余 100+",
    )
    is_active: Mapped[int] = mapped_column(TINYINT(1), nullable=False, default=1, comment="是否启用")

    def __repr__(self) -> str:
        return f"<CarrierPackingRule id={self.id} type={self.rule_type!r} name={self.name!r}>"
