# app/modules/inventory/services/inventory_transaction_service.py
"""
Inventory Transaction Service.

Provides query operations for inventory transaction history.
All transaction WRITES are handled by OrderInventoryService.
This service handles transaction READS for reporting and auditing.
"""

import logging

from sqlalchemy import func
from sqlalchemy.orm import Session

from app.modules.catalog.exceptions import ProductNotFoundException
from app.modules.inventory.models.inventory import Inventory
from app.modules.inventory.models.inventory_transaction import InventoryTransaction
from app.modules.orders.exceptions import OrderNotFoundException  # IMPORT-002

logger = logging.getLogger(__name__)


class InventoryTransactionService:
    """Service for querying inventory transaction history."""

    def get_store_transactions(
        self,
        db: Session,
        store_id: int,
        skip: int = 0,
        limit: int = 50,
        product_id: int | None = None,
        transaction_type: str | None = None,
    ) -> tuple[list[dict], int]:
        """
        Get inventory transactions for a store with optional filters.

        Args:
            db: Database session
            store_id: Store ID
            skip: Pagination offset
            limit: Pagination limit
            product_id: Optional product filter
            transaction_type: Optional transaction type filter

        Returns:
            Tuple of (transactions with product details, total count)
        """
        # Build query
        query = db.query(InventoryTransaction).filter(
            InventoryTransaction.store_id == store_id
        )

        # Apply filters
        if product_id:
            query = query.filter(InventoryTransaction.product_id == product_id)
        if transaction_type:
            query = query.filter(
                InventoryTransaction.transaction_type == transaction_type
            )

        # Get total count
        total = query.count()

        # Get transactions with pagination (newest first)
        transactions = (
            query.order_by(InventoryTransaction.created_at.desc())
            .offset(skip)
            .limit(limit)
            .all()
        )

        # Build result with product details
        from app.modules.catalog.services.product_service import product_service

        result = []
        for tx in transactions:
            product = product_service.get_product_by_id(db, tx.product_id)
            product_title = None
            product_sku = None
            if product:
                product_sku = product.store_sku
                if product.marketplace_product:
                    product_title = product.marketplace_product.get_title()

            result.append(
                {
                    "id": tx.id,
                    "store_id": tx.store_id,
                    "product_id": tx.product_id,
                    "inventory_id": tx.inventory_id,
                    "transaction_type": (
                        tx.transaction_type.value if tx.transaction_type else None
                    ),
                    "quantity_change": tx.quantity_change,
                    "quantity_after": tx.quantity_after,
                    "reserved_after": tx.reserved_after,
                    "location": tx.location,
                    "warehouse": tx.warehouse,
                    "order_id": tx.order_id,
                    "order_number": tx.order_number,
                    "reason": tx.reason,
                    "created_by": tx.created_by,
                    "created_at": tx.created_at,
                    "product_title": product_title,
                    "product_sku": product_sku,
                }
            )

        return result, total

    def get_product_history(
        self,
        db: Session,
        store_id: int,
        product_id: int,
        limit: int = 50,
    ) -> dict:
        """
        Get transaction history for a specific product.

        Args:
            db: Database session
            store_id: Store ID
            product_id: Product ID
            limit: Max transactions to return

        Returns:
            Dict with product info, current inventory, and transactions

        Raises:
            ProductNotFoundException: If product not found or doesn't belong to store
        """
        # Get product details
        from app.modules.catalog.services.product_service import product_service

        product = product_service.get_product_by_id(db, product_id)

        if not product or product.store_id != store_id:
            raise ProductNotFoundException(
                f"Product {product_id} not found in store catalog"
            )

        product_title = None
        product_sku = product.store_sku
        if product.marketplace_product:
            product_title = product.marketplace_product.get_title()

        # Get current inventory
        inventory = (
            db.query(Inventory)
            .filter(Inventory.product_id == product_id, Inventory.store_id == store_id)
            .first()
        )

        current_quantity = inventory.quantity if inventory else 0
        current_reserved = inventory.reserved_quantity if inventory else 0

        # Get transactions
        transactions = (
            db.query(InventoryTransaction)
            .filter(
                InventoryTransaction.store_id == store_id,
                InventoryTransaction.product_id == product_id,
            )
            .order_by(InventoryTransaction.created_at.desc())
            .limit(limit)
            .all()
        )

        total = (
            db.query(func.count(InventoryTransaction.id))
            .filter(
                InventoryTransaction.store_id == store_id,
                InventoryTransaction.product_id == product_id,
            )
            .scalar()
            or 0
        )

        return {
            "product_id": product_id,
            "product_title": product_title,
            "product_sku": product_sku,
            "current_quantity": current_quantity,
            "current_reserved": current_reserved,
            "transactions": [
                {
                    "id": tx.id,
                    "store_id": tx.store_id,
                    "product_id": tx.product_id,
                    "inventory_id": tx.inventory_id,
                    "transaction_type": (
                        tx.transaction_type.value if tx.transaction_type else None
                    ),
                    "quantity_change": tx.quantity_change,
                    "quantity_after": tx.quantity_after,
                    "reserved_after": tx.reserved_after,
                    "location": tx.location,
                    "warehouse": tx.warehouse,
                    "order_id": tx.order_id,
                    "order_number": tx.order_number,
                    "reason": tx.reason,
                    "created_by": tx.created_by,
                    "created_at": tx.created_at,
                }
                for tx in transactions
            ],
            "total": total,
        }

    def get_order_history(
        self,
        db: Session,
        store_id: int,
        order_id: int,
    ) -> dict:
        """
        Get all inventory transactions for a specific order.

        Args:
            db: Database session
            store_id: Store ID
            order_id: Order ID

        Returns:
            Dict with order info and transactions

        Raises:
            OrderNotFoundException: If order not found or doesn't belong to store
        """
        # Verify order belongs to store
        from app.modules.orders.services.order_service import (  # IMPORT-002
            order_service,
        )

        order = order_service.get_order_by_id(db, order_id, store_id=store_id)

        if not order:
            raise OrderNotFoundException(f"Order {order_id} not found")

        # Get transactions for this order
        transactions = (
            db.query(InventoryTransaction)
            .filter(InventoryTransaction.order_id == order_id)
            .order_by(InventoryTransaction.created_at.asc())
            .all()
        )

        # Build result with product details
        from app.modules.catalog.services.product_service import product_service

        result = []
        for tx in transactions:
            product = product_service.get_product_by_id(db, tx.product_id)
            product_title = None
            product_sku = None
            if product:
                product_sku = product.store_sku
                if product.marketplace_product:
                    product_title = product.marketplace_product.get_title()

            result.append(
                {
                    "id": tx.id,
                    "store_id": tx.store_id,
                    "product_id": tx.product_id,
                    "inventory_id": tx.inventory_id,
                    "transaction_type": (
                        tx.transaction_type.value if tx.transaction_type else None
                    ),
                    "quantity_change": tx.quantity_change,
                    "quantity_after": tx.quantity_after,
                    "reserved_after": tx.reserved_after,
                    "location": tx.location,
                    "warehouse": tx.warehouse,
                    "order_id": tx.order_id,
                    "order_number": tx.order_number,
                    "reason": tx.reason,
                    "created_by": tx.created_by,
                    "created_at": tx.created_at,
                    "product_title": product_title,
                    "product_sku": product_sku,
                }
            )

        return {
            "order_id": order_id,
            "order_number": order.order_number,
            "transactions": result,
        }


    # =========================================================================
    # Admin Methods (cross-store operations)
    # =========================================================================

    def get_all_transactions_admin(
        self,
        db: Session,
        skip: int = 0,
        limit: int = 50,
        store_id: int | None = None,
        product_id: int | None = None,
        transaction_type: str | None = None,
        order_id: int | None = None,
    ) -> tuple[list[dict], int]:
        """
        Get inventory transactions across all stores (admin only).

        Args:
            db: Database session
            skip: Pagination offset
            limit: Pagination limit
            store_id: Optional store filter
            product_id: Optional product filter
            transaction_type: Optional transaction type filter
            order_id: Optional order filter

        Returns:
            Tuple of (transactions with details, total count)
        """
        from app.modules.catalog.services.product_service import product_service
        from app.modules.tenancy.services.store_service import store_service

        # Build query
        query = db.query(InventoryTransaction)

        # Apply filters
        if store_id:
            query = query.filter(InventoryTransaction.store_id == store_id)
        if product_id:
            query = query.filter(InventoryTransaction.product_id == product_id)
        if transaction_type:
            query = query.filter(
                InventoryTransaction.transaction_type == transaction_type
            )
        if order_id:
            query = query.filter(InventoryTransaction.order_id == order_id)

        # Get total count
        total = query.count()

        # Get transactions with pagination (newest first)
        transactions = (
            query.order_by(InventoryTransaction.created_at.desc())
            .offset(skip)
            .limit(limit)
            .all()
        )

        # Build result with store and product details
        result = []
        for tx in transactions:
            store = store_service.get_store_by_id_optional(db, tx.store_id)
            product = product_service.get_product_by_id(db, tx.product_id)

            product_title = None
            product_sku = None
            if product:
                product_sku = product.store_sku
                if product.marketplace_product:
                    product_title = product.marketplace_product.get_title()

            result.append(
                {
                    "id": tx.id,
                    "store_id": tx.store_id,
                    "store_name": store.name if store else None,
                    "store_code": store.store_code if store else None,
                    "product_id": tx.product_id,
                    "inventory_id": tx.inventory_id,
                    "transaction_type": (
                        tx.transaction_type.value if tx.transaction_type else None
                    ),
                    "quantity_change": tx.quantity_change,
                    "quantity_after": tx.quantity_after,
                    "reserved_after": tx.reserved_after,
                    "location": tx.location,
                    "warehouse": tx.warehouse,
                    "order_id": tx.order_id,
                    "order_number": tx.order_number,
                    "reason": tx.reason,
                    "created_by": tx.created_by,
                    "created_at": tx.created_at,
                    "product_title": product_title,
                    "product_sku": product_sku,
                }
            )

        return result, total

    def get_transaction_stats_admin(self, db: Session) -> dict:
        """
        Get transaction statistics across the platform (admin only).

        Returns:
            Dict with transaction counts by type
        """
        from sqlalchemy import func as sql_func

        # Count by transaction type
        type_counts = (
            db.query(
                InventoryTransaction.transaction_type,
                sql_func.count(InventoryTransaction.id).label("count"),
            )
            .group_by(InventoryTransaction.transaction_type)
            .all()
        )

        # Total transactions
        total = db.query(sql_func.count(InventoryTransaction.id)).scalar() or 0

        # Transactions today
        from datetime import UTC, datetime

        today_start = datetime.now(UTC).replace(hour=0, minute=0, second=0, microsecond=0)
        today_count = (
            db.query(sql_func.count(InventoryTransaction.id))
            .filter(InventoryTransaction.created_at >= today_start)
            .scalar()
            or 0
        )

        return {
            "total_transactions": total,
            "transactions_today": today_count,
            "by_type": {tc.transaction_type.value: tc.count for tc in type_counts},
        }


# Create service instance
inventory_transaction_service = InventoryTransactionService()
