# ================================================================
# services/inventory/app/api/food_safety.py
# ================================================================
"""
Food Safety API endpoints for Inventory Service
"""

from datetime import datetime, timedelta
from typing import List, Optional
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query, Path, status
from sqlalchemy.ext.asyncio import AsyncSession
import structlog

from shared.auth.decorators import get_current_user_dep
from app.core.database import get_db
from app.services.food_safety_service import FoodSafetyService
from app.schemas.food_safety import (
    FoodSafetyComplianceCreate,
    FoodSafetyComplianceUpdate,
    FoodSafetyComplianceResponse,
    TemperatureLogCreate,
    TemperatureLogResponse,
    FoodSafetyAlertCreate,
    FoodSafetyAlertUpdate,
    FoodSafetyAlertResponse,
    BulkTemperatureLogCreate,
    FoodSafetyFilter,
    TemperatureMonitoringFilter,
    FoodSafetyMetrics,
    TemperatureAnalytics
)

logger = structlog.get_logger()

router = APIRouter(prefix="/food-safety", tags=["food-safety"])


# ===== Dependency Injection =====

async def get_food_safety_service() -> FoodSafetyService:
    """Get food safety service instance"""
    return FoodSafetyService()


# ===== Compliance Management Endpoints =====

@router.post("/tenants/{tenant_id}/compliance", response_model=FoodSafetyComplianceResponse, status_code=status.HTTP_201_CREATED)
async def create_compliance_record(
    compliance_data: FoodSafetyComplianceCreate,
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    food_safety_service: FoodSafetyService = Depends(get_food_safety_service),
    db: AsyncSession = Depends(get_db)
):
    """Create a new food safety compliance record"""
    try:
        # Ensure tenant_id matches
        compliance_data.tenant_id = tenant_id
        
        compliance = await food_safety_service.create_compliance_record(
            db, 
            compliance_data, 
            user_id=UUID(current_user["sub"])
        )
        
        logger.info("Compliance record created", 
                   compliance_id=str(compliance.id),
                   standard=compliance.standard)
        
        return compliance
        
    except ValueError as e:
        logger.warning("Invalid compliance data", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error("Error creating compliance record", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to create compliance record"
        )


@router.get("/tenants/{tenant_id}/compliance", response_model=List[FoodSafetyComplianceResponse])
async def get_compliance_records(
    tenant_id: UUID = Path(...),
    ingredient_id: Optional[UUID] = Query(None, description="Filter by ingredient ID"),
    standard: Optional[str] = Query(None, description="Filter by compliance standard"),
    status_filter: Optional[str] = Query(None, description="Filter by compliance status"),
    skip: int = Query(0, ge=0, description="Number of records to skip"),
    limit: int = Query(100, ge=1, le=1000, description="Number of records to return"),
    current_user: dict = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Get compliance records with filtering"""
    try:
        # Build query filters
        filters = {}
        if ingredient_id:
            filters["ingredient_id"] = ingredient_id
        if standard:
            filters["standard"] = standard
        if status_filter:
            filters["compliance_status"] = status_filter
        
        # Query compliance records
        query = """
            SELECT * FROM food_safety_compliance
            WHERE tenant_id = :tenant_id AND is_active = true
        """
        params = {"tenant_id": tenant_id}
        
        if filters:
            for key, value in filters.items():
                query += f" AND {key} = :{key}"
                params[key] = value
        
        query += " ORDER BY created_at DESC LIMIT :limit OFFSET :skip"
        params.update({"limit": limit, "skip": skip})
        
        result = await db.execute(query, params)
        records = result.fetchall()
        
        return [
            FoodSafetyComplianceResponse(**dict(record))
            for record in records
        ]
        
    except Exception as e:
        logger.error("Error getting compliance records", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to retrieve compliance records"
        )


@router.put("/tenants/{tenant_id}/compliance/{compliance_id}", response_model=FoodSafetyComplianceResponse)
async def update_compliance_record(
    compliance_data: FoodSafetyComplianceUpdate,
    tenant_id: UUID = Path(...),
    compliance_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    food_safety_service: FoodSafetyService = Depends(get_food_safety_service),
    db: AsyncSession = Depends(get_db)
):
    """Update an existing compliance record"""
    try:
        compliance = await food_safety_service.update_compliance_record(
            db,
            compliance_id,
            tenant_id,
            compliance_data,
            user_id=UUID(current_user["sub"])
        )
        
        if not compliance:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Compliance record not found"
            )
        
        logger.info("Compliance record updated", 
                   compliance_id=str(compliance.id))
        
        return compliance
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error updating compliance record", 
                    compliance_id=str(compliance_id), 
                    error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to update compliance record"
        )


# ===== Temperature Monitoring Endpoints =====

@router.post("/tenants/{tenant_id}/temperature", response_model=TemperatureLogResponse, status_code=status.HTTP_201_CREATED)
async def log_temperature(
    temp_data: TemperatureLogCreate,
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    food_safety_service: FoodSafetyService = Depends(get_food_safety_service),
    db: AsyncSession = Depends(get_db)
):
    """Log a temperature reading"""
    try:
        # Ensure tenant_id matches
        temp_data.tenant_id = tenant_id
        
        temp_log = await food_safety_service.log_temperature(
            db,
            temp_data,
            user_id=UUID(current_user["sub"])
        )
        
        logger.info("Temperature logged", 
                   location=temp_data.storage_location,
                   temperature=temp_data.temperature_celsius)
        
        return temp_log
        
    except Exception as e:
        logger.error("Error logging temperature", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to log temperature"
        )


@router.post("/tenants/{tenant_id}/temperature/bulk", response_model=List[TemperatureLogResponse])
async def bulk_log_temperatures(
    bulk_data: BulkTemperatureLogCreate,
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    food_safety_service: FoodSafetyService = Depends(get_food_safety_service),
    db: AsyncSession = Depends(get_db)
):
    """Bulk log temperature readings"""
    try:
        # Ensure tenant_id matches for all readings
        for reading in bulk_data.readings:
            reading.tenant_id = tenant_id
        
        temp_logs = await food_safety_service.bulk_log_temperatures(
            db,
            bulk_data.readings,
            user_id=UUID(current_user["sub"])
        )
        
        logger.info("Bulk temperature logging completed", 
                   count=len(bulk_data.readings))
        
        return temp_logs
        
    except Exception as e:
        logger.error("Error bulk logging temperatures", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to bulk log temperatures"
        )


@router.get("/tenants/{tenant_id}/temperature", response_model=List[TemperatureLogResponse])
async def get_temperature_logs(
    tenant_id: UUID = Path(...),
    location: Optional[str] = Query(None, description="Filter by storage location"),
    equipment_id: Optional[str] = Query(None, description="Filter by equipment ID"),
    date_from: Optional[datetime] = Query(None, description="Start date for filtering"),
    date_to: Optional[datetime] = Query(None, description="End date for filtering"),
    violations_only: bool = Query(False, description="Show only temperature violations"),
    skip: int = Query(0, ge=0, description="Number of records to skip"),
    limit: int = Query(100, ge=1, le=1000, description="Number of records to return"),
    current_user: dict = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Get temperature logs with filtering"""
    try:
        # Build query
        where_conditions = ["tenant_id = :tenant_id"]
        params = {"tenant_id": tenant_id}
        
        if location:
            where_conditions.append("storage_location ILIKE :location")
            params["location"] = f"%{location}%"
        
        if equipment_id:
            where_conditions.append("equipment_id = :equipment_id")
            params["equipment_id"] = equipment_id
        
        if date_from:
            where_conditions.append("recorded_at >= :date_from")
            params["date_from"] = date_from
        
        if date_to:
            where_conditions.append("recorded_at <= :date_to")
            params["date_to"] = date_to
        
        if violations_only:
            where_conditions.append("is_within_range = false")
        
        where_clause = " AND ".join(where_conditions)
        
        query = f"""
            SELECT * FROM temperature_logs
            WHERE {where_clause}
            ORDER BY recorded_at DESC
            LIMIT :limit OFFSET :skip
        """
        params.update({"limit": limit, "skip": skip})
        
        result = await db.execute(query, params)
        logs = result.fetchall()
        
        return [
            TemperatureLogResponse(**dict(log))
            for log in logs
        ]
        
    except Exception as e:
        logger.error("Error getting temperature logs", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to retrieve temperature logs"
        )


# ===== Alert Management Endpoints =====

@router.post("/tenants/{tenant_id}/alerts", response_model=FoodSafetyAlertResponse, status_code=status.HTTP_201_CREATED)
async def create_food_safety_alert(
    alert_data: FoodSafetyAlertCreate,
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    food_safety_service: FoodSafetyService = Depends(get_food_safety_service),
    db: AsyncSession = Depends(get_db)
):
    """Create a food safety alert"""
    try:
        # Ensure tenant_id matches
        alert_data.tenant_id = tenant_id
        
        alert = await food_safety_service.create_food_safety_alert(
            db,
            alert_data,
            user_id=UUID(current_user["sub"])
        )
        
        logger.info("Food safety alert created", 
                   alert_id=str(alert.id),
                   alert_type=alert.alert_type)
        
        return alert
        
    except Exception as e:
        logger.error("Error creating food safety alert", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to create food safety alert"
        )


@router.get("/tenants/{tenant_id}/alerts", response_model=List[FoodSafetyAlertResponse])
async def get_food_safety_alerts(
    tenant_id: UUID = Path(...),
    alert_type: Optional[str] = Query(None, description="Filter by alert type"),
    severity: Optional[str] = Query(None, description="Filter by severity"),
    status_filter: Optional[str] = Query(None, description="Filter by status"),
    unresolved_only: bool = Query(True, description="Show only unresolved alerts"),
    skip: int = Query(0, ge=0, description="Number of alerts to skip"),
    limit: int = Query(100, ge=1, le=1000, description="Number of alerts to return"),
    current_user: dict = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Get food safety alerts with filtering"""
    try:
        # Build query filters
        where_conditions = ["tenant_id = :tenant_id"]
        params = {"tenant_id": tenant_id}
        
        if alert_type:
            where_conditions.append("alert_type = :alert_type")
            params["alert_type"] = alert_type
        
        if severity:
            where_conditions.append("severity = :severity")
            params["severity"] = severity
        
        if status_filter:
            where_conditions.append("status = :status")
            params["status"] = status_filter
        elif unresolved_only:
            where_conditions.append("status NOT IN ('resolved', 'dismissed')")
        
        where_clause = " AND ".join(where_conditions)
        
        query = f"""
            SELECT * FROM food_safety_alerts
            WHERE {where_clause}
            ORDER BY created_at DESC
            LIMIT :limit OFFSET :skip
        """
        params.update({"limit": limit, "skip": skip})
        
        result = await db.execute(query, params)
        alerts = result.fetchall()
        
        return [
            FoodSafetyAlertResponse(**dict(alert))
            for alert in alerts
        ]
        
    except Exception as e:
        logger.error("Error getting food safety alerts", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to retrieve food safety alerts"
        )


@router.put("/tenants/{tenant_id}/alerts/{alert_id}", response_model=FoodSafetyAlertResponse)
async def update_food_safety_alert(
    alert_data: FoodSafetyAlertUpdate,
    tenant_id: UUID = Path(...),
    alert_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Update a food safety alert"""
    try:
        # Get existing alert
        alert_query = "SELECT * FROM food_safety_alerts WHERE id = :alert_id AND tenant_id = :tenant_id"
        result = await db.execute(alert_query, {"alert_id": alert_id, "tenant_id": tenant_id})
        alert_record = result.fetchone()
        
        if not alert_record:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Food safety alert not found"
            )
        
        # Update alert fields
        update_fields = alert_data.dict(exclude_unset=True)
        if update_fields:
            set_clauses = []
            params = {"alert_id": alert_id, "tenant_id": tenant_id}
            
            for field, value in update_fields.items():
                set_clauses.append(f"{field} = :{field}")
                params[field] = value
            
            # Add updated timestamp and user
            set_clauses.append("updated_at = NOW()")
            set_clauses.append("updated_by = :updated_by")
            params["updated_by"] = UUID(current_user["sub"])
            
            update_query = f"""
                UPDATE food_safety_alerts
                SET {', '.join(set_clauses)}
                WHERE id = :alert_id AND tenant_id = :tenant_id
            """
            
            await db.execute(update_query, params)
            await db.commit()
        
        # Get updated alert
        result = await db.execute(alert_query, {"alert_id": alert_id, "tenant_id": tenant_id})
        updated_alert = result.fetchone()
        
        logger.info("Food safety alert updated", 
                   alert_id=str(alert_id))
        
        return FoodSafetyAlertResponse(**dict(updated_alert))
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error updating food safety alert", 
                    alert_id=str(alert_id), 
                    error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to update food safety alert"
        )


@router.post("/tenants/{tenant_id}/alerts/{alert_id}/acknowledge")
async def acknowledge_alert(
    tenant_id: UUID = Path(...),
    alert_id: UUID = Path(...),
    notes: Optional[str] = Query(None, description="Acknowledgment notes"),
    current_user: dict = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Acknowledge a food safety alert"""
    try:
        # Update alert to acknowledged status
        update_query = """
            UPDATE food_safety_alerts
            SET status = 'acknowledged',
                acknowledged_at = NOW(),
                acknowledged_by = :user_id,
                investigation_notes = COALESCE(investigation_notes, '') || :notes,
                updated_at = NOW(),
                updated_by = :user_id
            WHERE id = :alert_id AND tenant_id = :tenant_id
        """
        
        result = await db.execute(update_query, {
            "alert_id": alert_id,
            "tenant_id": tenant_id,
            "user_id": UUID(current_user["sub"]),
            "notes": f"\nAcknowledged: {notes}" if notes else "\nAcknowledged"
        })
        
        if result.rowcount == 0:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Food safety alert not found"
            )
        
        await db.commit()
        
        logger.info("Food safety alert acknowledged", 
                   alert_id=str(alert_id))
        
        return {"message": "Alert acknowledged successfully"}
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error acknowledging alert", 
                    alert_id=str(alert_id), 
                    error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to acknowledge alert"
        )


# ===== Analytics and Reporting Endpoints =====

@router.get("/tenants/{tenant_id}/metrics", response_model=FoodSafetyMetrics)
async def get_food_safety_metrics(
    tenant_id: UUID = Path(...),
    days_back: int = Query(30, ge=1, le=365, description="Number of days to analyze"),
    current_user: dict = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Get food safety performance metrics"""
    try:
        # Calculate compliance rate
        compliance_query = """
            SELECT 
                COUNT(*) as total,
                COUNT(CASE WHEN compliance_status = 'compliant' THEN 1 END) as compliant
            FROM food_safety_compliance
            WHERE tenant_id = :tenant_id AND is_active = true
        """
        
        result = await db.execute(compliance_query, {"tenant_id": tenant_id})
        compliance_stats = result.fetchone()
        
        compliance_rate = 0.0
        if compliance_stats.total > 0:
            compliance_rate = (compliance_stats.compliant / compliance_stats.total) * 100
        
        # Calculate temperature compliance
        temp_query = """
            SELECT 
                COUNT(*) as total_readings,
                COUNT(CASE WHEN is_within_range THEN 1 END) as compliant_readings
            FROM temperature_logs
            WHERE tenant_id = :tenant_id 
            AND recorded_at > NOW() - INTERVAL '%s days'
        """ % days_back
        
        result = await db.execute(temp_query, {"tenant_id": tenant_id})
        temp_stats = result.fetchone()
        
        temp_compliance_rate = 0.0
        if temp_stats.total_readings > 0:
            temp_compliance_rate = (temp_stats.compliant_readings / temp_stats.total_readings) * 100
        
        # Get alert metrics
        alert_query = """
            SELECT 
                COUNT(*) as total_alerts,
                COUNT(CASE WHEN is_recurring THEN 1 END) as recurring_alerts,
                COUNT(CASE WHEN regulatory_action_required THEN 1 END) as regulatory_violations,
                AVG(CASE WHEN response_time_minutes IS NOT NULL THEN response_time_minutes END) as avg_response_time,
                AVG(CASE WHEN resolution_time_minutes IS NOT NULL THEN resolution_time_minutes END) as avg_resolution_time
            FROM food_safety_alerts
            WHERE tenant_id = :tenant_id 
            AND created_at > NOW() - INTERVAL '%s days'
        """ % days_back
        
        result = await db.execute(alert_query, {"tenant_id": tenant_id})
        alert_stats = result.fetchone()
        
        return FoodSafetyMetrics(
            compliance_rate=Decimal(str(compliance_rate)),
            temperature_compliance_rate=Decimal(str(temp_compliance_rate)),
            alert_response_time_avg=Decimal(str(alert_stats.avg_response_time or 0)),
            alert_resolution_time_avg=Decimal(str(alert_stats.avg_resolution_time or 0)),
            recurring_issues_count=alert_stats.recurring_alerts or 0,
            regulatory_violations=alert_stats.regulatory_violations or 0,
            certification_coverage=Decimal(str(compliance_rate)),  # Same as compliance rate for now
            audit_score_avg=Decimal("85.0"),  # Would calculate from actual audit data
            risk_score=Decimal("3.2")  # Would calculate from risk assessments
        )
        
    except Exception as e:
        logger.error("Error getting food safety metrics", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to retrieve food safety metrics"
        )


# ===== Health and Status Endpoints =====

@router.get("/tenants/{tenant_id}/status")
async def get_food_safety_status(
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep)
):
    """Get food safety service status"""
    try:
        return {
            "service": "food-safety",
            "status": "healthy",
            "timestamp": datetime.now().isoformat(),
            "tenant_id": str(tenant_id),
            "features": {
                "compliance_tracking": "enabled",
                "temperature_monitoring": "enabled",
                "automated_alerts": "enabled",
                "regulatory_reporting": "enabled"
            }
        }
        
    except Exception as e:
        logger.error("Error getting food safety status", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get food safety status"
        )