# services/inventory/app/main.py
"""
Inventory Service FastAPI Application
"""

import os
from fastapi import FastAPI
from sqlalchemy import text

# Import core modules
from app.core.config import settings
from app.core.database import database_manager
from app.services.inventory_alert_service import InventoryAlertService
from app.services.inventory_scheduler import InventoryScheduler
from app.consumers.delivery_event_consumer import DeliveryEventConsumer
from shared.service_base import StandardFastAPIService
from shared.messaging import UnifiedEventPublisher
import asyncio

from app.api import (
    internal_demo,
    batch,
    ingredients,
    stock_entries,
    transformations,
    inventory_operations,
    food_safety_compliance,
    temperature_logs,
    food_safety_alerts,
    food_safety_operations,
    dashboard,
    analytics,
    sustainability,
    audit,
    ml_insights,
    enterprise_inventory,
    internal
)
from app.api.internal_alert_trigger import router as internal_alert_trigger_router
from app.api.internal_demo import router as internal_demo_router


class InventoryService(StandardFastAPIService):
    """Inventory Service with standardized setup"""

    expected_migration_version = "20251123_unified_initial_schema"

    async def verify_migrations(self):
        """Verify database schema matches the latest migrations."""
        try:
            async with self.database_manager.get_session() as session:
                result = await session.execute(text("SELECT version_num FROM alembic_version"))
                version = result.scalar()
                if version != self.expected_migration_version:
                    self.logger.error(f"Migration version mismatch: expected {self.expected_migration_version}, got {version}")
                    raise RuntimeError(f"Migration version mismatch: expected {self.expected_migration_version}, got {version}")
                self.logger.info(f"Migration verification successful: {version}")
        except Exception as e:
            self.logger.error(f"Migration verification failed: {e}")
            raise

    def __init__(self):
        # Define expected database tables for health checks
        inventory_expected_tables = [
            'ingredients', 'stock', 'stock_movements', 'product_transformations',
            'stock_alerts', 'food_safety_compliance', 'temperature_logs', 'food_safety_alerts'
        ]

        # Initialize delivery consumer and rabbitmq client
        self.delivery_consumer = None
        self.delivery_consumer_task = None
        self.rabbitmq_client = None

        super().__init__(
            service_name="inventory-service",
            app_name=settings.APP_NAME,
            description=settings.DESCRIPTION,
            version=settings.VERSION,
            log_level=settings.LOG_LEVEL,
            cors_origins=settings.CORS_ORIGINS,
            api_prefix="",  # Empty because RouteBuilder already includes /api/v1
            database_manager=database_manager,
            expected_tables=inventory_expected_tables,
            enable_messaging=True  # Enable RabbitMQ for event consumption
        )

    async def _setup_messaging(self):
        """Setup messaging for inventory service"""
        from shared.messaging import RabbitMQClient
        try:
            self.rabbitmq_client = RabbitMQClient(settings.RABBITMQ_URL, service_name="inventory-service")
            await self.rabbitmq_client.connect()
            # Create event publisher
            self.event_publisher = UnifiedEventPublisher(self.rabbitmq_client, "inventory-service")
            self.logger.info("Inventory service messaging setup completed")
        except Exception as e:
            self.logger.error("Failed to setup inventory messaging", error=str(e))
            raise

    async def _cleanup_messaging(self):
        """Cleanup messaging for inventory service"""
        try:
            if self.rabbitmq_client:
                await self.rabbitmq_client.disconnect()
                self.logger.info("Inventory service messaging cleanup completed")
        except Exception as e:
            self.logger.error("Error during inventory messaging cleanup", error=str(e))

    async def on_startup(self, app: FastAPI):
        """Custom startup logic for inventory service"""
        # Verify migrations first
        await self.verify_migrations()

        # Call parent startup (includes database, messaging, etc.)
        await super().on_startup(app)

        # Initialize alert service with EventPublisher
        if self.event_publisher:
            alert_service = InventoryAlertService(self.event_publisher)
            await alert_service.start()
            self.logger.info("Inventory alert service started")

            # Initialize inventory scheduler with alert service, database manager, and Redis URL for leader election
            inventory_scheduler = InventoryScheduler(
                alert_service,
                self.database_manager,
                redis_url=settings.REDIS_URL  # Pass Redis URL for leader election in multi-replica deployments
            )
            await inventory_scheduler.start()
            self.logger.info("Inventory scheduler started")

            # Store services in app state
            app.state.alert_service = alert_service
            app.state.inventory_scheduler = inventory_scheduler  # Store scheduler for manual triggering
            app.state.event_publisher = self.event_publisher  # Store event publisher for ML insights
        else:
            self.logger.error("Event publisher not initialized, alert service unavailable")

        # Initialize and start delivery event consumer
        self.delivery_consumer = DeliveryEventConsumer()

        # Start consuming delivery.received events in background
        if self.rabbitmq_client and self.rabbitmq_client.connected:
            self.delivery_consumer_task = asyncio.create_task(
                self.delivery_consumer.consume_delivery_received_events(self.rabbitmq_client)
            )
            self.logger.info("Delivery event consumer started successfully")
        else:
            self.logger.warning("RabbitMQ not connected, delivery event consumer not started")

        app.state.delivery_consumer = self.delivery_consumer

    async def on_shutdown(self, app: FastAPI):
        """Custom shutdown logic for inventory service"""
        # Stop inventory scheduler
        if hasattr(app.state, 'inventory_scheduler') and app.state.inventory_scheduler:
            await app.state.inventory_scheduler.stop()
            self.logger.info("Inventory scheduler stopped")

        # Cancel delivery consumer task
        if self.delivery_consumer_task and not self.delivery_consumer_task.done():
            self.delivery_consumer_task.cancel()
            try:
                await self.delivery_consumer_task
            except asyncio.CancelledError:
                self.logger.info("Delivery event consumer task cancelled")

        # Stop alert service
        if hasattr(app.state, 'alert_service'):
            await app.state.alert_service.stop()
            self.logger.info("Alert service stopped")

        await super().on_shutdown(app)

    def get_service_features(self):
        """Return inventory-specific features"""
        return [
            "ingredient_management",
            "stock_tracking",
            "expiration_alerts",
            "low_stock_alerts",
            "batch_tracking",
            "fifo_consumption",
            "barcode_support",
            "food_safety_compliance",
            "temperature_monitoring",
            "dashboard_analytics",
            "business_model_detection",
            "real_time_alerts",
            "regulatory_reporting",
            "sustainability_tracking",
            "sdg_compliance",
            "environmental_impact",
            "grant_reporting"
        ]


# Create service instance
service = InventoryService()

# Create FastAPI app with standardized setup
app = service.create_app()

# Setup standard endpoints
service.setup_standard_endpoints()

# Include new standardized routers
# IMPORTANT: Register audit router FIRST to avoid route matching conflicts
service.add_router(audit.router)
service.add_router(batch.router)
service.add_router(ingredients.router)
service.add_router(stock_entries.router)
service.add_router(transformations.router)
service.add_router(inventory_operations.router)
service.add_router(food_safety_compliance.router)
service.add_router(temperature_logs.router)
service.add_router(food_safety_alerts.router)
service.add_router(food_safety_operations.router)
service.add_router(dashboard.router)
service.add_router(analytics.router)
service.add_router(sustainability.router)
service.add_router(internal_demo.router, tags=["internal-demo"])
service.add_router(internal.router)
service.add_router(ml_insights.router)  # ML insights endpoint
service.add_router(ml_insights.internal_router)  # Internal ML insights endpoint for demo cloning
service.add_router(internal_alert_trigger_router)  # Internal alert trigger for demo cloning
service.add_router(enterprise_inventory.router)  # Enterprise inventory endpoints


if __name__ == "__main__":
    import uvicorn
    
    uvicorn.run(
        "app.main:app",
        host="0.0.0.0",
        port=8000,
        reload=os.getenv("RELOAD", "false").lower() == "true",
        log_level="info"
    )
