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


class ShippingZone(Base, TenantMixin, TimestampMixin):
    """运费区域（地理分组）

    匹配逻辑（按 sort_order 升序依次尝试）：
    1. 若 is_all_countries=1，匹配所有地址（兜底区域）
    2. 若 province_rules 里有该国家的省份列表，且收件省份在列表中 → 匹配
    3. 若 countries 里有该国家代码 → 匹配（省级兜底）
    """

    __tablename__ = "shipping_zones"
    __table_args__ = (
        Index("ix_zone_tenant_sort", "tenant_id", "sort_order"),
        Index("ix_zone_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(100), nullable=False, comment="区域名称，如 新西兰北岛 / 澳大利亚")
    description: Mapped[str | None] = mapped_column(String(500), nullable=True)
    countries: Mapped[list | None] = mapped_column(
        JSON, nullable=True,
        comment='ISO 3166-1 alpha-2 国家代码列表，如 ["NZ","AU"]'
    )
    province_rules: Mapped[dict | None] = mapped_column(
        JSON, nullable=True,
        comment='精细到省份的规则，如 {"NZ":["Auckland","Wellington"],"AU":["NSW"]}'
    )
    is_all_countries: Mapped[int] = mapped_column(
        TINYINT(1), nullable=False, default=0,
        comment="1=覆盖所有国家（兜底区域），优先级最低"
    )
    sort_order: Mapped[int] = mapped_column(Integer, nullable=False, default=0, comment="匹配优先级，越小越先尝试")
    is_active: Mapped[int] = mapped_column(TINYINT(1), nullable=False, default=1)

    methods = relationship("ShippingMethod", back_populates="zone", lazy="noload")

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