# app/modules/loyalty/services/category_service.py
"""
Transaction category CRUD service.

Store-scoped categories (e.g., Men, Women, Accessories) that sellers
select when entering loyalty transactions.
"""

import logging

from sqlalchemy.orm import Session

from app.modules.loyalty.models.transaction_category import StoreTransactionCategory
from app.modules.loyalty.schemas.category import CategoryCreate, CategoryUpdate

logger = logging.getLogger(__name__)

MAX_CATEGORIES_PER_STORE = 10


class CategoryService:
    """CRUD operations for store transaction categories."""

    def list_categories(
        self, db: Session, store_id: int, active_only: bool = False
    ) -> list[StoreTransactionCategory]:
        """List categories for a store, ordered by display_order."""
        query = db.query(StoreTransactionCategory).filter(
            StoreTransactionCategory.store_id == store_id
        )
        if active_only:
            query = query.filter(StoreTransactionCategory.is_active == True)  # noqa: E712
        return query.order_by(StoreTransactionCategory.display_order).all()

    def create_category(
        self, db: Session, store_id: int, data: CategoryCreate
    ) -> StoreTransactionCategory:
        """Create a new category for a store."""
        # Check max limit
        count = (
            db.query(StoreTransactionCategory)
            .filter(StoreTransactionCategory.store_id == store_id)
            .count()
        )
        if count >= MAX_CATEGORIES_PER_STORE:
            from app.modules.loyalty.exceptions import LoyaltyException

            raise LoyaltyException(
                message=f"Maximum {MAX_CATEGORIES_PER_STORE} categories per store",
                error_code="MAX_CATEGORIES_REACHED",
            )

        # Check duplicate name
        existing = (
            db.query(StoreTransactionCategory)
            .filter(
                StoreTransactionCategory.store_id == store_id,
                StoreTransactionCategory.name == data.name,
            )
            .first()
        )
        if existing:
            from app.modules.loyalty.exceptions import LoyaltyException

            raise LoyaltyException(
                message=f"Category '{data.name}' already exists",
                error_code="DUPLICATE_CATEGORY",
            )

        category = StoreTransactionCategory(
            store_id=store_id,
            name=data.name,
            display_order=data.display_order,
        )
        db.add(category)
        db.commit()
        db.refresh(category)

        logger.info(f"Created category '{data.name}' for store {store_id}")
        return category

    def update_category(
        self,
        db: Session,
        category_id: int,
        store_id: int,
        data: CategoryUpdate,
    ) -> StoreTransactionCategory:
        """Update a category (ownership check via store_id)."""
        category = (
            db.query(StoreTransactionCategory)
            .filter(
                StoreTransactionCategory.id == category_id,
                StoreTransactionCategory.store_id == store_id,
            )
            .first()
        )
        if not category:
            from app.modules.loyalty.exceptions import LoyaltyException

            raise LoyaltyException(
                message="Category not found",
                error_code="CATEGORY_NOT_FOUND",
                status_code=404,
            )

        update_data = data.model_dump(exclude_unset=True)
        for field, value in update_data.items():
            setattr(category, field, value)

        db.commit()
        db.refresh(category)
        return category

    def delete_category(
        self, db: Session, category_id: int, store_id: int
    ) -> None:
        """Delete a category (ownership check via store_id)."""
        category = (
            db.query(StoreTransactionCategory)
            .filter(
                StoreTransactionCategory.id == category_id,
                StoreTransactionCategory.store_id == store_id,
            )
            .first()
        )
        if not category:
            from app.modules.loyalty.exceptions import LoyaltyException

            raise LoyaltyException(
                message="Category not found",
                error_code="CATEGORY_NOT_FOUND",
                status_code=404,
            )

        db.delete(category)
        db.commit()
        logger.info(f"Deleted category {category_id} from store {store_id}")

    def validate_category_for_store(
        self, db: Session, category_id: int, store_id: int, lang: str = "en"
    ) -> str | None:
        """Validate that a category belongs to the store.

        Returns the translated category name if valid, None if not found.
        """
        category = (
            db.query(StoreTransactionCategory)
            .filter(
                StoreTransactionCategory.id == category_id,
                StoreTransactionCategory.store_id == store_id,
                StoreTransactionCategory.is_active == True,  # noqa: E712
            )
            .first()
        )
        if not category:
            return None
        return category.get_translated_name(lang)


# Singleton
category_service = CategoryService()
