# shared/clients/suppliers_client.py
"""
Suppliers Service Client for Inter-Service Communication
Provides access to supplier data and performance metrics from other services
"""

import structlog
from typing import Dict, Any, Optional, List
from shared.clients.base_service_client import BaseServiceClient
from shared.config.base import BaseServiceSettings

logger = structlog.get_logger()


class SuppliersServiceClient(BaseServiceClient):
    """Client for communicating with the Suppliers Service"""
    
    def __init__(self, config: BaseServiceSettings):
        super().__init__("suppliers", config)
    
    def get_service_base_path(self) -> str:
        return "/api/v1"
    
    # ================================================================
    # SUPPLIER MANAGEMENT
    # ================================================================
    
    async def get_supplier_by_id(self, tenant_id: str, supplier_id: str) -> Optional[Dict[str, Any]]:
        """Get supplier details by ID"""
        try:
            result = await self.get(f"suppliers/{supplier_id}", tenant_id=tenant_id)
            if result:
                logger.info("Retrieved supplier details from suppliers service", 
                          supplier_id=supplier_id, tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error getting supplier details", 
                        error=str(e), supplier_id=supplier_id, tenant_id=tenant_id)
            return None
    
    async def get_all_suppliers(self, tenant_id: str, is_active: Optional[bool] = True) -> Optional[List[Dict[str, Any]]]:
        """Get all suppliers for a tenant"""
        try:
            params = {}
            if is_active is not None:
                params["is_active"] = is_active
                
            result = await self.get_paginated("suppliers", tenant_id=tenant_id, params=params)
            logger.info("Retrieved all suppliers from suppliers service", 
                      suppliers_count=len(result), tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error getting all suppliers", 
                        error=str(e), tenant_id=tenant_id)
            return []
    
    async def search_suppliers(self, tenant_id: str, search: Optional[str] = None, category: Optional[str] = None) -> Optional[List[Dict[str, Any]]]:
        """Search suppliers with filters"""
        try:
            params = {}
            if search:
                params["search"] = search
            if category:
                params["category"] = category
                
            result = await self.get("suppliers/search", tenant_id=tenant_id, params=params)
            suppliers = result.get('suppliers', []) if result else []
            logger.info("Searched suppliers from suppliers service", 
                      search_term=search, suppliers_count=len(suppliers), tenant_id=tenant_id)
            return suppliers
        except Exception as e:
            logger.error("Error searching suppliers", 
                        error=str(e), tenant_id=tenant_id)
            return []
    
    # ================================================================
    # SUPPLIER RECOMMENDATIONS
    # ================================================================
    
    async def get_supplier_recommendations(self, tenant_id: str, ingredient_id: str) -> Optional[Dict[str, Any]]:
        """Get supplier recommendations for procurement"""
        try:
            params = {"ingredient_id": ingredient_id}
            result = await self.get("recommendations", tenant_id=tenant_id, params=params)
            if result:
                logger.info("Retrieved supplier recommendations from suppliers service", 
                          ingredient_id=ingredient_id, tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error getting supplier recommendations", 
                        error=str(e), ingredient_id=ingredient_id, tenant_id=tenant_id)
            return None
    
    async def get_best_supplier_for_ingredient(self, tenant_id: str, ingredient_id: str, criteria: Optional[Dict[str, Any]] = None) -> Optional[Dict[str, Any]]:
        """Get best supplier for a specific ingredient based on criteria"""
        try:
            data = {
                "ingredient_id": ingredient_id,
                "criteria": criteria or {}
            }
            result = await self.post("find-best-supplier", data=data, tenant_id=tenant_id)
            if result:
                logger.info("Retrieved best supplier from suppliers service", 
                          ingredient_id=ingredient_id, tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error getting best supplier for ingredient", 
                        error=str(e), ingredient_id=ingredient_id, tenant_id=tenant_id)
            return None
    
    # ================================================================
    # PURCHASE ORDER MANAGEMENT
    # ================================================================
    
    async def create_purchase_order(self, tenant_id: str, order_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
        """Create a new purchase order"""
        try:
            result = await self.post("purchase-orders", data=order_data, tenant_id=tenant_id)
            if result:
                logger.info("Created purchase order", 
                          order_id=result.get('id'), 
                          supplier_id=order_data.get('supplier_id'),
                          tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error creating purchase order", 
                        error=str(e), tenant_id=tenant_id)
            return None
    
    async def get_purchase_orders(self, tenant_id: str, status: Optional[str] = None, supplier_id: Optional[str] = None) -> Optional[List[Dict[str, Any]]]:
        """Get purchase orders with optional filtering"""
        try:
            params = {}
            if status:
                params["status"] = status
            if supplier_id:
                params["supplier_id"] = supplier_id
                
            result = await self.get("purchase-orders", tenant_id=tenant_id, params=params)
            orders = result.get('orders', []) if result else []
            logger.info("Retrieved purchase orders from suppliers service", 
                      orders_count=len(orders), tenant_id=tenant_id)
            return orders
        except Exception as e:
            logger.error("Error getting purchase orders", 
                        error=str(e), tenant_id=tenant_id)
            return []
    
    async def update_purchase_order_status(self, tenant_id: str, order_id: str, status: str) -> Optional[Dict[str, Any]]:
        """Update purchase order status"""
        try:
            data = {"status": status}
            result = await self.put(f"purchase-orders/{order_id}/status", data=data, tenant_id=tenant_id)
            if result:
                logger.info("Updated purchase order status", 
                          order_id=order_id, status=status, tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error updating purchase order status", 
                        error=str(e), order_id=order_id, tenant_id=tenant_id)
            return None
    
    # ================================================================
    # DELIVERY MANAGEMENT
    # ================================================================
    
    async def get_deliveries(self, tenant_id: str, status: Optional[str] = None, date: Optional[str] = None) -> Optional[List[Dict[str, Any]]]:
        """Get deliveries with optional filtering"""
        try:
            params = {}
            if status:
                params["status"] = status
            if date:
                params["date"] = date
                
            result = await self.get("deliveries", tenant_id=tenant_id, params=params)
            deliveries = result.get('deliveries', []) if result else []
            logger.info("Retrieved deliveries from suppliers service", 
                      deliveries_count=len(deliveries), tenant_id=tenant_id)
            return deliveries
        except Exception as e:
            logger.error("Error getting deliveries", 
                        error=str(e), tenant_id=tenant_id)
            return []
    
    async def update_delivery_status(self, tenant_id: str, delivery_id: str, status: str, notes: Optional[str] = None) -> Optional[Dict[str, Any]]:
        """Update delivery status"""
        try:
            data = {"status": status}
            if notes:
                data["notes"] = notes
                
            result = await self.put(f"deliveries/{delivery_id}/status", data=data, tenant_id=tenant_id)
            if result:
                logger.info("Updated delivery status", 
                          delivery_id=delivery_id, status=status, tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error updating delivery status", 
                        error=str(e), delivery_id=delivery_id, tenant_id=tenant_id)
            return None
    
    async def get_supplier_order_summaries(self, tenant_id: str) -> Optional[Dict[str, Any]]:
        """Get supplier order summaries for central bakery dashboard"""
        try:
            result = await self.get("supplier-order-summaries", tenant_id=tenant_id)
            if result:
                logger.info("Retrieved supplier order summaries from suppliers service", 
                          tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error getting supplier order summaries", 
                        error=str(e), tenant_id=tenant_id)
            return None
    
    # ================================================================
    # PERFORMANCE TRACKING
    # ================================================================
    
    async def get_supplier_performance(self, tenant_id: str, supplier_id: str, period: str = "last_30_days") -> Optional[Dict[str, Any]]:
        """Get supplier performance metrics"""
        try:
            params = {"period": period}
            result = await self.get(f"suppliers/{supplier_id}/performance", tenant_id=tenant_id, params=params)
            if result:
                logger.info("Retrieved supplier performance from suppliers service", 
                          supplier_id=supplier_id, period=period, tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error getting supplier performance", 
                        error=str(e), supplier_id=supplier_id, tenant_id=tenant_id)
            return None
    
    async def get_performance_alerts(self, tenant_id: str) -> Optional[List[Dict[str, Any]]]:
        """Get supplier performance alerts"""
        try:
            result = await self.get("performance-alerts", tenant_id=tenant_id)
            alerts = result.get('alerts', []) if result else []
            logger.info("Retrieved supplier performance alerts", 
                      alerts_count=len(alerts), tenant_id=tenant_id)
            return alerts
        except Exception as e:
            logger.error("Error getting supplier performance alerts", 
                        error=str(e), tenant_id=tenant_id)
            return []
    
    async def record_supplier_rating(self, tenant_id: str, supplier_id: str, rating_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
        """Record a rating/review for a supplier"""
        try:
            result = await self.post(f"suppliers/{supplier_id}/rating", data=rating_data, tenant_id=tenant_id)
            if result:
                logger.info("Recorded supplier rating", 
                          supplier_id=supplier_id, tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error recording supplier rating", 
                        error=str(e), supplier_id=supplier_id, tenant_id=tenant_id)
            return None
    
    # ================================================================
    # DASHBOARD AND ANALYTICS
    # ================================================================
    
    async def get_dashboard_summary(self, tenant_id: str) -> Optional[Dict[str, Any]]:
        """Get suppliers dashboard summary data"""
        try:
            result = await self.get("dashboard-summary", tenant_id=tenant_id)
            if result:
                logger.info("Retrieved suppliers dashboard summary", 
                          tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error getting suppliers dashboard summary", 
                        error=str(e), tenant_id=tenant_id)
            return None
    
    async def get_cost_analysis(self, tenant_id: str, start_date: str, end_date: str) -> Optional[Dict[str, Any]]:
        """Get cost analysis across suppliers"""
        try:
            params = {
                "start_date": start_date,
                "end_date": end_date
            }
            result = await self.get("cost-analysis", tenant_id=tenant_id, params=params)
            if result:
                logger.info("Retrieved supplier cost analysis", 
                          start_date=start_date, end_date=end_date, tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error getting supplier cost analysis", 
                        error=str(e), tenant_id=tenant_id)
            return None
    
    async def get_supplier_reliability_metrics(self, tenant_id: str) -> Optional[Dict[str, Any]]:
        """Get supplier reliability and quality metrics"""
        try:
            result = await self.get("reliability-metrics", tenant_id=tenant_id)
            if result:
                logger.info("Retrieved supplier reliability metrics", 
                          tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error getting supplier reliability metrics", 
                        error=str(e), tenant_id=tenant_id)
            return None
    
    # ================================================================
    # ALERTS AND NOTIFICATIONS
    # ================================================================
    
    async def acknowledge_alert(self, tenant_id: str, alert_id: str) -> Optional[Dict[str, Any]]:
        """Acknowledge a supplier-related alert"""
        try:
            result = await self.post(f"alerts/{alert_id}/acknowledge", data={}, tenant_id=tenant_id)
            if result:
                logger.info("Acknowledged supplier alert", 
                          alert_id=alert_id, tenant_id=tenant_id)
            return result
        except Exception as e:
            logger.error("Error acknowledging supplier alert", 
                        error=str(e), alert_id=alert_id, tenant_id=tenant_id)
            return None
    
    # ================================================================
    # UTILITY METHODS
    # ================================================================
    
    async def health_check(self) -> bool:
        """Check if suppliers service is healthy"""
        try:
            result = await self.get("../health")  # Health endpoint is not tenant-scoped
            return result is not None
        except Exception as e:
            logger.error("Suppliers service health check failed", error=str(e))
            return False


# Factory function for dependency injection
def create_suppliers_client(config: BaseServiceSettings) -> SuppliersServiceClient:
    """Create suppliers service client instance"""
    return SuppliersServiceClient(config)