# ================================================================
# services/forecasting/app/jobs/daily_validation.py
# ================================================================
"""
Daily Validation Job

Scheduled job to validate previous day's forecasts against actual sales.
This job is called by the orchestrator as part of the daily workflow.
"""

from typing import Dict, Any, Optional
from datetime import datetime, timedelta, timezone
import structlog
import uuid

from app.services.validation_service import ValidationService
from app.core.database import database_manager

logger = structlog.get_logger()


async def daily_validation_job(
    tenant_id: uuid.UUID,
    orchestration_run_id: Optional[uuid.UUID] = None
) -> Dict[str, Any]:
    """
    Validate yesterday's forecasts against actual sales

    This function is designed to be called by the orchestrator as part of
    the daily workflow (Step 5: validate_previous_forecasts).

    Args:
        tenant_id: Tenant identifier
        orchestration_run_id: Optional orchestration run ID for tracking

    Returns:
        Dictionary with validation results
    """
    async with database_manager.get_session() as db:
        try:
            logger.info(
                "Starting daily validation job",
                tenant_id=tenant_id,
                orchestration_run_id=orchestration_run_id
            )

            validation_service = ValidationService(db)

            # Validate yesterday's forecasts
            result = await validation_service.validate_yesterday(
                tenant_id=tenant_id,
                orchestration_run_id=orchestration_run_id,
                triggered_by="orchestrator"
            )

            logger.info(
                "Daily validation job completed",
                tenant_id=tenant_id,
                validation_run_id=result.get("validation_run_id"),
                forecasts_evaluated=result.get("forecasts_evaluated"),
                forecasts_with_actuals=result.get("forecasts_with_actuals"),
                overall_mape=result.get("overall_metrics", {}).get("mape")
            )

            return result

        except Exception as e:
            logger.error(
                "Daily validation job failed",
                tenant_id=tenant_id,
                orchestration_run_id=orchestration_run_id,
                error=str(e),
                error_type=type(e).__name__
            )
            return {
                "status": "failed",
                "error": str(e),
                "tenant_id": str(tenant_id),
                "orchestration_run_id": str(orchestration_run_id) if orchestration_run_id else None
            }


async def validate_date_range_job(
    tenant_id: uuid.UUID,
    start_date: datetime,
    end_date: datetime,
    orchestration_run_id: Optional[uuid.UUID] = None
) -> Dict[str, Any]:
    """
    Validate forecasts for a specific date range

    Useful for backfilling validation metrics when historical data is uploaded.

    Args:
        tenant_id: Tenant identifier
        start_date: Start of validation period
        end_date: End of validation period
        orchestration_run_id: Optional orchestration run ID for tracking

    Returns:
        Dictionary with validation results
    """
    async with database_manager.get_session() as db:
        try:
            logger.info(
                "Starting date range validation job",
                tenant_id=tenant_id,
                start_date=start_date.isoformat(),
                end_date=end_date.isoformat(),
                orchestration_run_id=orchestration_run_id
            )

            validation_service = ValidationService(db)

            result = await validation_service.validate_date_range(
                tenant_id=tenant_id,
                start_date=start_date,
                end_date=end_date,
                orchestration_run_id=orchestration_run_id,
                triggered_by="scheduled"
            )

            logger.info(
                "Date range validation job completed",
                tenant_id=tenant_id,
                validation_run_id=result.get("validation_run_id"),
                forecasts_evaluated=result.get("forecasts_evaluated"),
                forecasts_with_actuals=result.get("forecasts_with_actuals")
            )

            return result

        except Exception as e:
            logger.error(
                "Date range validation job failed",
                tenant_id=tenant_id,
                start_date=start_date.isoformat(),
                end_date=end_date.isoformat(),
                error=str(e),
                error_type=type(e).__name__
            )
            return {
                "status": "failed",
                "error": str(e),
                "tenant_id": str(tenant_id),
                "orchestration_run_id": str(orchestration_run_id) if orchestration_run_id else None
            }
