# app/modules/loyalty/models/merchant_settings.py
"""
Merchant loyalty settings database model.

Admin-controlled settings that apply to a merchant's loyalty program.
These settings are managed by platform administrators, not stores.
"""

import enum

from sqlalchemy import (
    Boolean,
    Column,
    ForeignKey,
    Index,
    Integer,
    String,
)
from sqlalchemy.orm import relationship

from app.core.database import Base
from models.database.base import TimestampMixin


class StaffPinPolicy(str, enum.Enum):
    """Staff PIN policy options."""

    REQUIRED = "required"  # Staff PIN always required
    OPTIONAL = "optional"  # Store can choose
    DISABLED = "disabled"  # Staff PIN not used


class MerchantLoyaltySettings(Base, TimestampMixin):
    """
    Admin-controlled settings for merchant loyalty programs.

    These settings are managed by platform administrators and
    cannot be changed by stores. They apply to all stores
    within the merchant.
    """

    __tablename__ = "merchant_loyalty_settings"

    id = Column(Integer, primary_key=True, index=True)

    # Merchant association (one settings per merchant)
    merchant_id = Column(
        Integer,
        ForeignKey("merchants.id", ondelete="CASCADE"),
        unique=True,
        nullable=False,
        index=True,
        comment="Merchant these settings apply to",
    )

    # =========================================================================
    # Staff PIN Policy (Admin-controlled)
    # =========================================================================
    staff_pin_policy = Column(
        String(20),
        default=StaffPinPolicy.REQUIRED,
        nullable=False,
        comment="Staff PIN policy: required, optional, disabled",
    )
    staff_pin_lockout_attempts = Column(
        Integer,
        default=5,
        nullable=False,
        comment="Max failed PIN attempts before lockout",
    )
    staff_pin_lockout_minutes = Column(
        Integer,
        default=30,
        nullable=False,
        comment="Lockout duration in minutes",
    )

    # =========================================================================
    # Feature Toggles (Admin-controlled)
    # =========================================================================
    allow_self_enrollment = Column(
        Boolean,
        default=True,
        nullable=False,
        comment="Allow customers to self-enroll via QR code",
    )
    allow_void_transactions = Column(
        Boolean,
        default=True,
        nullable=False,
        comment="Allow voiding points for returns",
    )
    allow_cross_location_redemption = Column(
        Boolean,
        default=True,
        nullable=False,
        comment="Allow redemption at any merchant location",
    )

    # =========================================================================
    # Audit Settings
    # =========================================================================
    require_order_reference = Column(
        Boolean,
        default=False,
        nullable=False,
        comment="Require order reference when earning points",
    )
    log_ip_addresses = Column(
        Boolean,
        default=True,
        nullable=False,
        comment="Log IP addresses for transactions",
    )

    # =========================================================================
    # Relationships
    # =========================================================================
    merchant = relationship("Merchant", backref="loyalty_settings")

    # Indexes
    __table_args__ = (
        Index("idx_merchant_loyalty_settings_merchant", "merchant_id"),
    )

    def __repr__(self) -> str:
        return f"<MerchantLoyaltySettings(id={self.id}, merchant_id={self.merchant_id}, pin_policy='{self.staff_pin_policy}')>"

    @property
    def is_staff_pin_required(self) -> bool:
        """Check if staff PIN is required."""
        return self.staff_pin_policy == StaffPinPolicy.REQUIRED

    @property
    def is_staff_pin_disabled(self) -> bool:
        """Check if staff PIN is disabled."""
        return self.staff_pin_policy == StaffPinPolicy.DISABLED
