# ================================================================
# services/forecasting/app/models/forecasts.py
# ================================================================
"""
Forecast models for the forecasting service
"""

from sqlalchemy import Column, String, Integer, Float, DateTime, Boolean, Text, JSON, UniqueConstraint, Index
from sqlalchemy.dialects.postgresql import UUID
from datetime import datetime, timezone
import uuid

from shared.database.base import Base

class Forecast(Base):
    """Forecast model for storing prediction results"""
    __tablename__ = "forecasts"

    __table_args__ = (
        # Unique constraint to prevent duplicate forecasts
        # Ensures only one forecast per (tenant, product, date, location) combination
        UniqueConstraint(
            'tenant_id', 'inventory_product_id', 'forecast_date', 'location',
            name='uq_forecast_tenant_product_date_location'
        ),
        # Composite index for common query patterns
        Index('ix_forecasts_tenant_product_date', 'tenant_id', 'inventory_product_id', 'forecast_date'),
    )

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
    inventory_product_id = Column(UUID(as_uuid=True), nullable=False, index=True)  # Reference to inventory service
    product_name = Column(String(255), nullable=True, index=True)  # Product name (optional - use inventory_product_id as reference)
    location = Column(String(255), nullable=False, index=True)
    
    # Forecast period
    forecast_date = Column(DateTime(timezone=True), nullable=False, index=True)
    created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
    
    # Prediction results
    predicted_demand = Column(Float, nullable=False)
    confidence_lower = Column(Float, nullable=False)
    confidence_upper = Column(Float, nullable=False)
    confidence_level = Column(Float, default=0.8)
    
    # Model information
    model_id = Column(String(255), nullable=False)
    model_version = Column(String(50), nullable=False)
    algorithm = Column(String(50), default="prophet")
    
    # Business context
    business_type = Column(String(50), default="individual")  # individual or central_workshop
    day_of_week = Column(Integer, nullable=False)
    is_holiday = Column(Boolean, default=False)
    is_weekend = Column(Boolean, default=False)
    
    # External factors
    weather_temperature = Column(Float)
    weather_precipitation = Column(Float)
    weather_description = Column(String(100))
    traffic_volume = Column(Integer)
    
    # Metadata
    processing_time_ms = Column(Integer)
    features_used = Column(JSON)
    
    def __repr__(self):
        return f"<Forecast(id={self.id}, inventory_product_id={self.inventory_product_id}, date={self.forecast_date})>"

class PredictionBatch(Base):
    """Batch prediction requests"""
    __tablename__ = "prediction_batches"
    
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
    
    # Batch information
    batch_name = Column(String(255), nullable=False)
    requested_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
    completed_at = Column(DateTime(timezone=True))
    
    # Status
    status = Column(String(50), default="pending")  # pending, processing, completed, failed
    total_products = Column(Integer, default=0)
    completed_products = Column(Integer, default=0)
    failed_products = Column(Integer, default=0)
    
    # Configuration
    forecast_days = Column(Integer, default=7)
    business_type = Column(String(50), default="individual")
    
    # Results
    error_message = Column(Text)
    processing_time_ms = Column(Integer)
    
    cancelled_by = Column(String, nullable=True)
    
    def __repr__(self):
        return f"<PredictionBatch(id={self.id}, status={self.status})>"


