"""
Enhanced Forecast API Endpoints with Repository Pattern
Updated to use repository pattern with dependency injection and improved error handling
"""

import structlog
from fastapi import APIRouter, Depends, HTTPException, status, Query, Path, Request
from typing import List, Optional
from datetime import date, datetime
import uuid

from app.services.forecasting_service import EnhancedForecastingService
from app.schemas.forecasts import (
    ForecastRequest, ForecastResponse, BatchForecastRequest,
    BatchForecastResponse, MultiDayForecastResponse
)
from shared.auth.decorators import (
    get_current_user_dep,
    require_admin_role
)
from shared.database.base import create_database_manager
from shared.monitoring.decorators import track_execution_time
from shared.monitoring.metrics import get_metrics_collector
from app.core.config import settings

logger = structlog.get_logger()
router = APIRouter(tags=["enhanced-forecasts"])

def get_enhanced_forecasting_service():
    """Dependency injection for EnhancedForecastingService"""
    database_manager = create_database_manager(settings.DATABASE_URL, "forecasting-service")
    return EnhancedForecastingService(database_manager)

@router.post("/tenants/{tenant_id}/forecasts/single", response_model=ForecastResponse)
@track_execution_time("enhanced_single_forecast_duration_seconds", "forecasting-service")
async def create_enhanced_single_forecast(
    request: ForecastRequest,
    tenant_id: str = Path(..., description="Tenant ID"),
    request_obj: Request = None,
    enhanced_forecasting_service: EnhancedForecastingService = Depends(get_enhanced_forecasting_service)
):
    """Generate a single product forecast using enhanced repository pattern"""
    metrics = get_metrics_collector(request_obj)
    
    try:
        logger.info("Generating enhanced single forecast",
                   tenant_id=tenant_id,
                   inventory_product_id=request.inventory_product_id,
                   forecast_date=request.forecast_date.isoformat())
        
        # Record metrics
        if metrics:
            metrics.increment_counter("enhanced_single_forecasts_total")
        
        # Generate forecast using enhanced service
        forecast = await enhanced_forecasting_service.generate_forecast(
            tenant_id=tenant_id,
            request=request
        )
        
        if metrics:
            metrics.increment_counter("enhanced_single_forecasts_success_total")
        
        logger.info("Enhanced single forecast generated successfully",
                   tenant_id=tenant_id,
                   forecast_id=forecast.id)
        
        return forecast

    except ValueError as e:
        if metrics:
            metrics.increment_counter("enhanced_forecast_validation_errors_total")
        logger.error("Enhanced forecast validation error",
                    error=str(e),
                    tenant_id=tenant_id)
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        if metrics:
            metrics.increment_counter("enhanced_single_forecasts_errors_total")
        logger.error("Enhanced single forecast generation failed",
                    error=str(e),
                    tenant_id=tenant_id)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Enhanced forecast generation failed"
        )


@router.post("/tenants/{tenant_id}/forecasts/multi-day", response_model=MultiDayForecastResponse)
@track_execution_time("enhanced_multi_day_forecast_duration_seconds", "forecasting-service")
async def create_enhanced_multi_day_forecast(
    request: ForecastRequest,
    tenant_id: str = Path(..., description="Tenant ID"),
    request_obj: Request = None,
    enhanced_forecasting_service: EnhancedForecastingService = Depends(get_enhanced_forecasting_service)
):
    """Generate multiple daily forecasts for the specified period using enhanced repository pattern"""
    metrics = get_metrics_collector(request_obj)

    try:
        logger.info("Generating enhanced multi-day forecast",
                   tenant_id=tenant_id,
                   inventory_product_id=request.inventory_product_id,
                   forecast_days=request.forecast_days,
                   forecast_date=request.forecast_date.isoformat())

        # Record metrics
        if metrics:
            metrics.increment_counter("enhanced_multi_day_forecasts_total")

        # Validate forecast_days parameter
        if request.forecast_days <= 0 or request.forecast_days > 30:
            raise ValueError("forecast_days must be between 1 and 30")

        # Generate multi-day forecast using enhanced service
        forecast_result = await enhanced_forecasting_service.generate_multi_day_forecast(
            tenant_id=tenant_id,
            request=request
        )

        if metrics:
            metrics.increment_counter("enhanced_multi_day_forecasts_success_total")

        logger.info("Enhanced multi-day forecast generated successfully",
                   tenant_id=tenant_id,
                   inventory_product_id=request.inventory_product_id,
                   forecast_days=len(forecast_result.get("forecasts", [])))

        return MultiDayForecastResponse(**forecast_result)

    except ValueError as e:
        if metrics:
            metrics.increment_counter("enhanced_multi_day_forecast_validation_errors_total")
        logger.error("Enhanced multi-day forecast validation error",
                    error=str(e),
                    tenant_id=tenant_id)
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        if metrics:
            metrics.increment_counter("enhanced_multi_day_forecasts_errors_total")
        logger.error("Enhanced multi-day forecast generation failed",
                    error=str(e),
                    tenant_id=tenant_id)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Enhanced multi-day forecast generation failed"
        )


@router.post("/tenants/{tenant_id}/forecasts/batch", response_model=BatchForecastResponse)
@track_execution_time("enhanced_batch_forecast_duration_seconds", "forecasting-service")
async def create_enhanced_batch_forecast(
    request: BatchForecastRequest,
    tenant_id: str = Path(..., description="Tenant ID"),
    request_obj: Request = None,
    enhanced_forecasting_service: EnhancedForecastingService = Depends(get_enhanced_forecasting_service)
):
    """Generate batch forecasts using enhanced repository pattern"""
    metrics = get_metrics_collector(request_obj)
    
    try:
        logger.info("Generating enhanced batch forecasts",
                   tenant_id=tenant_id,
                   products_count=len(request.inventory_product_ids),
                   forecast_dates_count=request.forecast_days)
        
        # Record metrics
        if metrics:
            metrics.increment_counter("enhanced_batch_forecasts_total")
            metrics.histogram("enhanced_batch_forecast_products_count", len(request.inventory_product_ids))
        
        # Generate batch forecasts using enhanced service
        batch_result = await enhanced_forecasting_service.generate_batch_forecasts(
            tenant_id=tenant_id,
            request=request
        )
        
        if metrics:
            metrics.increment_counter("enhanced_batch_forecasts_success_total")
        
        logger.info("Enhanced batch forecasts generated successfully",
                   tenant_id=tenant_id,
                   batch_id=batch_result.get("batch_id"),
                   forecasts_generated=len(batch_result.get("forecasts", [])))
        
        return BatchForecastResponse(**batch_result)
        
    except ValueError as e:
        if metrics:
            metrics.increment_counter("enhanced_batch_forecast_validation_errors_total")
        logger.error("Enhanced batch forecast validation error",
                    error=str(e),
                    tenant_id=tenant_id)
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        if metrics:
            metrics.increment_counter("enhanced_batch_forecasts_errors_total")
        logger.error("Enhanced batch forecast generation failed",
                    error=str(e),
                    tenant_id=tenant_id)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Enhanced batch forecast generation failed"
        )


@router.get("/tenants/{tenant_id}/forecasts")
@track_execution_time("enhanced_get_forecasts_duration_seconds", "forecasting-service")
async def get_enhanced_tenant_forecasts(
    tenant_id: str = Path(..., description="Tenant ID"),
    inventory_product_id: Optional[str] = Query(None, description="Filter by inventory product ID"),
    start_date: Optional[date] = Query(None, description="Start date filter"),
    end_date: Optional[date] = Query(None, description="End date filter"),
    skip: int = Query(0, description="Number of records to skip"),
    limit: int = Query(100, description="Number of records to return"),
    request_obj: Request = None,
    enhanced_forecasting_service: EnhancedForecastingService = Depends(get_enhanced_forecasting_service)
):
    """Get tenant forecasts with enhanced filtering using repository pattern"""
    metrics = get_metrics_collector(request_obj)
    
    try:
        # Record metrics
        if metrics:
            metrics.increment_counter("enhanced_get_forecasts_total")
        
        # Get forecasts using enhanced service
        forecasts = await enhanced_forecasting_service.get_tenant_forecasts(
            tenant_id=tenant_id,
            inventory_product_id=inventory_product_id,
            start_date=start_date,
            end_date=end_date,
            skip=skip,
            limit=limit
        )
        
        if metrics:
            metrics.increment_counter("enhanced_get_forecasts_success_total")
        
        return {
            "tenant_id": tenant_id,
            "forecasts": forecasts,
            "total_returned": len(forecasts),
            "filters": {
                "inventory_product_id": inventory_product_id,
                "start_date": start_date.isoformat() if start_date else None,
                "end_date": end_date.isoformat() if end_date else None
            },
            "pagination": {
                "skip": skip,
                "limit": limit
            },
            "enhanced_features": True,
            "repository_integration": True
        }
        
    except Exception as e:
        if metrics:
            metrics.increment_counter("enhanced_get_forecasts_errors_total")
        logger.error("Failed to get enhanced tenant forecasts",
                    tenant_id=tenant_id,
                    error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get tenant forecasts"
        )




@router.get("/tenants/{tenant_id}/forecasts/{forecast_id}")
@track_execution_time("enhanced_get_forecast_duration_seconds", "forecasting-service")
async def get_enhanced_forecast_by_id(
    tenant_id: str = Path(..., description="Tenant ID"),
    forecast_id: str = Path(..., description="Forecast ID"),
    request_obj: Request = None,
    enhanced_forecasting_service: EnhancedForecastingService = Depends(get_enhanced_forecasting_service)
):
    """Get specific forecast by ID using enhanced repository pattern"""
    metrics = get_metrics_collector(request_obj)
    
    try:
        # Record metrics
        if metrics:
            metrics.increment_counter("enhanced_get_forecast_by_id_total")
        
        # Get forecast using enhanced service
        forecast = await enhanced_forecasting_service.get_forecast_by_id(forecast_id)
        
        if not forecast:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Forecast not found"
            )
        
        if metrics:
            metrics.increment_counter("enhanced_get_forecast_by_id_success_total")
        
        return {
            **forecast,
            "enhanced_features": True,
            "repository_integration": True
        }
        
    except HTTPException:
        raise
    except Exception as e:
        if metrics:
            metrics.increment_counter("enhanced_get_forecast_by_id_errors_total")
        logger.error("Failed to get enhanced forecast by ID",
                    forecast_id=forecast_id,
                    error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get forecast"
        )


@router.delete("/tenants/{tenant_id}/forecasts/{forecast_id}")
@track_execution_time("enhanced_delete_forecast_duration_seconds", "forecasting-service")
async def delete_enhanced_forecast(
    tenant_id: str = Path(..., description="Tenant ID"),
    forecast_id: str = Path(..., description="Forecast ID"),
    request_obj: Request = None,
    enhanced_forecasting_service: EnhancedForecastingService = Depends(get_enhanced_forecasting_service)
):
    """Delete forecast using enhanced repository pattern"""
    metrics = get_metrics_collector(request_obj)
    
    try:
        # Record metrics
        if metrics:
            metrics.increment_counter("enhanced_delete_forecast_total")
        
        # Delete forecast using enhanced service
        deleted = await enhanced_forecasting_service.delete_forecast(forecast_id)
        
        if not deleted:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Forecast not found"
            )
        
        if metrics:
            metrics.increment_counter("enhanced_delete_forecast_success_total")
        
        logger.info("Enhanced forecast deleted successfully",
                   forecast_id=forecast_id,
                   tenant_id=tenant_id)
        
        return {
            "message": "Forecast deleted successfully",
            "forecast_id": forecast_id,
            "enhanced_features": True,
            "repository_integration": True
        }
        
    except HTTPException:
        raise
    except Exception as e:
        if metrics:
            metrics.increment_counter("enhanced_delete_forecast_errors_total")
        logger.error("Failed to delete enhanced forecast",
                    forecast_id=forecast_id,
                    error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to delete forecast"
        )


@router.get("/tenants/{tenant_id}/forecasts/statistics")
@track_execution_time("enhanced_forecast_statistics_duration_seconds", "forecasting-service")
async def get_enhanced_forecast_statistics(
    tenant_id: str = Path(..., description="Tenant ID"),
    request_obj: Request = None,
    enhanced_forecasting_service: EnhancedForecastingService = Depends(get_enhanced_forecasting_service)
):
    """Get comprehensive forecast statistics using enhanced repository pattern"""
    metrics = get_metrics_collector(request_obj)
    
    try:
        # Record metrics
        if metrics:
            metrics.increment_counter("enhanced_forecast_statistics_total")
        
        # Get statistics using enhanced service
        statistics = await enhanced_forecasting_service.get_tenant_forecast_statistics(tenant_id)
        
        if statistics.get("error"):
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=statistics["error"]
            )
        
        if metrics:
            metrics.increment_counter("enhanced_forecast_statistics_success_total")
        
        return {
            **statistics,
            "enhanced_features": True,
            "repository_integration": True
        }
        
    except HTTPException:
        raise
    except Exception as e:
        if metrics:
            metrics.increment_counter("enhanced_forecast_statistics_errors_total")
        logger.error("Failed to get enhanced forecast statistics",
                    tenant_id=tenant_id,
                    error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get forecast statistics"
        )


@router.get("/health")
async def enhanced_health_check():
    """Enhanced health check endpoint for the forecasting service"""
    return {
        "status": "healthy",
        "service": "enhanced-forecasting-service",
        "version": "2.0.0",
        "features": [
            "repository-pattern",
            "dependency-injection", 
            "enhanced-error-handling",
            "metrics-tracking",
            "transactional-operations",
            "batch-processing"
        ],
        "timestamp": datetime.now().isoformat()
    }