# services/inventory/app/repositories/food_safety_repository.py
"""
Food Safety Repository
Data access layer for food safety compliance and monitoring
"""

from typing import List, Optional, Dict, Any
from uuid import UUID
from datetime import datetime
from sqlalchemy import text, select
from sqlalchemy.ext.asyncio import AsyncSession
import structlog

from app.models.food_safety import (
    FoodSafetyCompliance,
    FoodSafetyAlert,
    TemperatureLog,
    ComplianceStatus
)

logger = structlog.get_logger()


class FoodSafetyRepository:
    """Repository for food safety data access"""

    def __init__(self, session: AsyncSession):
        self.session = session

    # ===== COMPLIANCE METHODS =====

    async def create_compliance(self, compliance: FoodSafetyCompliance) -> FoodSafetyCompliance:
        """
        Create a new compliance record

        Args:
            compliance: FoodSafetyCompliance instance

        Returns:
            Created FoodSafetyCompliance instance
        """
        self.session.add(compliance)
        await self.session.flush()
        await self.session.refresh(compliance)
        return compliance

    async def get_compliance_by_id(
        self,
        compliance_id: UUID,
        tenant_id: UUID
    ) -> Optional[FoodSafetyCompliance]:
        """
        Get compliance record by ID

        Args:
            compliance_id: Compliance record UUID
            tenant_id: Tenant UUID for authorization

        Returns:
            FoodSafetyCompliance or None
        """
        compliance = await self.session.get(FoodSafetyCompliance, compliance_id)
        if compliance and compliance.tenant_id == tenant_id:
            return compliance
        return None

    async def update_compliance(
        self,
        compliance: FoodSafetyCompliance
    ) -> FoodSafetyCompliance:
        """
        Update compliance record

        Args:
            compliance: FoodSafetyCompliance instance with updates

        Returns:
            Updated FoodSafetyCompliance instance
        """
        await self.session.flush()
        await self.session.refresh(compliance)
        return compliance

    async def get_compliance_stats(self, tenant_id: UUID) -> Dict[str, int]:
        """
        Get compliance statistics for dashboard

        Args:
            tenant_id: Tenant UUID

        Returns:
            Dictionary with compliance counts by status
        """
        try:
            query = text("""
                SELECT
                    COUNT(*) as total,
                    COUNT(CASE WHEN compliance_status = 'COMPLIANT' THEN 1 END) as compliant,
                    COUNT(CASE WHEN compliance_status = 'NON_COMPLIANT' THEN 1 END) as non_compliant,
                    COUNT(CASE WHEN compliance_status = 'PENDING_REVIEW' THEN 1 END) as pending_review
                FROM food_safety_compliance
                WHERE tenant_id = :tenant_id AND is_active = true
            """)

            result = await self.session.execute(query, {"tenant_id": tenant_id})
            row = result.fetchone()

            if not row:
                return {
                    "total": 0,
                    "compliant": 0,
                    "non_compliant": 0,
                    "pending_review": 0
                }

            return {
                "total": row.total or 0,
                "compliant": row.compliant or 0,
                "non_compliant": row.non_compliant or 0,
                "pending_review": row.pending_review or 0
            }
        except Exception as e:
            logger.error("Failed to get compliance stats", error=str(e), tenant_id=str(tenant_id))
            raise

    # ===== TEMPERATURE MONITORING METHODS =====

    async def get_temperature_stats(self, tenant_id: UUID) -> Dict[str, Any]:
        """
        Get temperature monitoring statistics

        Args:
            tenant_id: Tenant UUID

        Returns:
            Dictionary with temperature monitoring stats
        """
        try:
            query = text("""
                SELECT
                    COUNT(DISTINCT equipment_id) as sensors_online,
                    COUNT(CASE WHEN NOT is_within_range AND recorded_at > NOW() - INTERVAL '24 hours' THEN 1 END) as violations_24h
                FROM temperature_logs
                WHERE tenant_id = :tenant_id AND recorded_at > NOW() - INTERVAL '1 hour'
            """)

            result = await self.session.execute(query, {"tenant_id": tenant_id})
            row = result.fetchone()

            if not row:
                return {
                    "sensors_online": 0,
                    "violations_24h": 0
                }

            return {
                "sensors_online": row.sensors_online or 0,
                "violations_24h": row.violations_24h or 0
            }
        except Exception as e:
            logger.error("Failed to get temperature stats", error=str(e), tenant_id=str(tenant_id))
            raise

    # ===== EXPIRATION TRACKING METHODS =====

    async def get_expiration_stats(self, tenant_id: UUID) -> Dict[str, int]:
        """
        Get expiration tracking statistics

        Args:
            tenant_id: Tenant UUID

        Returns:
            Dictionary with expiration counts
        """
        try:
            query = text("""
                SELECT
                    COUNT(CASE WHEN expiration_date::date = CURRENT_DATE THEN 1 END) as expiring_today,
                    COUNT(CASE WHEN expiration_date BETWEEN CURRENT_DATE AND CURRENT_DATE + INTERVAL '7 days' THEN 1 END) as expiring_week,
                    COUNT(CASE WHEN expiration_date < CURRENT_DATE AND is_available THEN 1 END) as expired_requiring_action
                FROM stock s
                JOIN ingredients i ON s.ingredient_id = i.id
                WHERE i.tenant_id = :tenant_id AND s.is_available = true
            """)

            result = await self.session.execute(query, {"tenant_id": tenant_id})
            row = result.fetchone()

            if not row:
                return {
                    "expiring_today": 0,
                    "expiring_week": 0,
                    "expired_requiring_action": 0
                }

            return {
                "expiring_today": row.expiring_today or 0,
                "expiring_week": row.expiring_week or 0,
                "expired_requiring_action": row.expired_requiring_action or 0
            }
        except Exception as e:
            logger.error("Failed to get expiration stats", error=str(e), tenant_id=str(tenant_id))
            raise

    # ===== ALERT METHODS =====

    async def get_alert_stats(self, tenant_id: UUID) -> Dict[str, int]:
        """
        Get food safety alert statistics

        Args:
            tenant_id: Tenant UUID

        Returns:
            Dictionary with alert counts by severity
        """
        try:
            query = text("""
                SELECT
                    COUNT(CASE WHEN severity = 'high' OR severity = 'critical' THEN 1 END) as high_risk,
                    COUNT(CASE WHEN severity = 'critical' THEN 1 END) as critical,
                    COUNT(CASE WHEN regulatory_action_required = true AND resolved_at IS NULL THEN 1 END) as regulatory_pending
                FROM food_safety_alerts
                WHERE tenant_id = :tenant_id AND status = 'active'
            """)

            result = await self.session.execute(query, {"tenant_id": tenant_id})
            row = result.fetchone()

            if not row:
                return {
                    "high_risk": 0,
                    "critical": 0,
                    "regulatory_pending": 0
                }

            return {
                "high_risk": row.high_risk or 0,
                "critical": row.critical or 0,
                "regulatory_pending": row.regulatory_pending or 0
            }
        except Exception as e:
            logger.error("Failed to get alert stats", error=str(e), tenant_id=str(tenant_id))
            raise

    # ===== VALIDATION METHODS =====

    async def validate_ingredient_exists(
        self,
        ingredient_id: UUID,
        tenant_id: UUID
    ) -> bool:
        """
        Validate that an ingredient exists for a tenant

        Args:
            ingredient_id: Ingredient UUID
            tenant_id: Tenant UUID

        Returns:
            True if ingredient exists, False otherwise
        """
        try:
            query = text("""
                SELECT id
                FROM ingredients
                WHERE id = :ingredient_id AND tenant_id = :tenant_id
            """)

            result = await self.session.execute(query, {
                "ingredient_id": ingredient_id,
                "tenant_id": tenant_id
            })

            return result.fetchone() is not None
        except Exception as e:
            logger.error("Failed to validate ingredient", error=str(e))
            raise

    async def mark_temperature_alert_triggered(self, log_id: UUID) -> None:
        """
        Mark a temperature log as having triggered an alert
        """
        try:
            query = text("""
                UPDATE temperature_logs
                SET alert_triggered = true
                WHERE id = :id
            """)

            await self.session.execute(query, {"id": log_id})
            await self.session.commit()

        except Exception as e:
            await self.session.rollback()
            logger.error("Failed to mark temperature alert", error=str(e), log_id=str(log_id))
            raise
