"""FastAPI application for ReflowManager service."""

import os
from typing import Dict, Any, List, Optional
from fastapi import FastAPI, HTTPException, Depends, status, BackgroundTasks
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session

from reflowfy.reflow_manager.database import get_db, init_db
from reflowfy.reflow_manager.manager import ReflowManager
from reflowfy.reflow_manager.schemas import (
    CreateExecutionRequest,
    UpdateExecutionStateRequest,
    DispatchJobsRequest,
    CheckpointRequest,
    RunPipelineRequest,
)
from reflowfy.reflow_manager.dlq_routes import router as dlq_router
from reflowfy.reflow_manager.dlq_scheduler import (
    init_dlq_scheduler,
    stop_dlq_scheduler,
)


# Create FastAPI app
app = FastAPI(
    title="ReflowManager",
    description="Pipeline state management and rate limiting service",
    version="1.0.0",
)

# CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Include DLQ router
app.include_router(dlq_router)


# Dependency to get ReflowManager instance
def get_reflow_manager(db: Session = Depends(get_db)) -> ReflowManager:
    """Get ReflowManager instance with database session."""
    kafka_bootstrap_servers = os.getenv("KAFKA_BOOTSTRAP_SERVERS", "localhost:9092")
    kafka_topic = os.getenv("KAFKA_TOPIC", "reflow.jobs")
    max_jobs_per_second = float(os.getenv("MAX_JOBS_PER_SECOND", "100"))
    execution_mode = os.getenv("EXECUTION_MODE", "distributed")
    
    return ReflowManager(
        db_session=db,
        kafka_bootstrap_servers=kafka_bootstrap_servers,
        kafka_topic=kafka_topic,
        max_jobs_per_second=max_jobs_per_second,
        execution_mode=execution_mode,
    )
    
# ... (intermediate code preserved implicitly via context matching in generic implementation, but here applied explicitly)

@app.post("/run", status_code=status.HTTP_202_ACCEPTED)
async def run_pipeline(
    request: RunPipelineRequest,
    background_tasks: BackgroundTasks,
    db: Session = Depends(get_db),
):
    # ...
        # Get ReflowManager config from environment
        kafka_bootstrap_servers = os.getenv("KAFKA_BOOTSTRAP_SERVERS", "localhost:9092")
        kafka_topic = os.getenv("KAFKA_TOPIC", "reflow.jobs")
        max_jobs_per_second = float(os.getenv("MAX_JOBS_PER_SECOND", "100"))
        execution_mode = os.getenv("EXECUTION_MODE", "distributed")
        
        # Create initial execution record (pending state)
        manager = ReflowManager(
            db_session=db,
            kafka_bootstrap_servers=kafka_bootstrap_servers,
            kafka_topic=kafka_topic,
            max_jobs_per_second=max_jobs_per_second,
            execution_mode=execution_mode,
        )
        # ...

def _dispatch_pipeline_jobs(
    execution_id: str,
    pipeline_name: str,
    runtime_params: dict,
    rate_limit_override: Optional[float] = None,
):
    """Background task to dispatch pipeline jobs."""
    from reflowfy.reflow_manager.database import SessionLocal
    
    # Create a new database session for background task
    db = SessionLocal()
    
    try:
        kafka_bootstrap_servers = os.getenv("KAFKA_BOOTSTRAP_SERVERS", "localhost:9092")
        kafka_topic = os.getenv("KAFKA_TOPIC", "reflow.jobs")
        max_jobs_per_second = float(os.getenv("MAX_JOBS_PER_SECOND", "100"))
        execution_mode = os.getenv("EXECUTION_MODE", "distributed")
        
        manager = ReflowManager(
            db_session=db,
            kafka_bootstrap_servers=kafka_bootstrap_servers,
            kafka_topic=kafka_topic,
            max_jobs_per_second=max_jobs_per_second,
            execution_mode=execution_mode,
        )
        # ...
        
    # ...

@app.on_event("startup")
async def startup_event():
    # ...
    # Initialize DLQ scheduler
    print("\n📬 Initializing DLQ scheduler...")
    try:
        def pipeline_runner_factory():
            from reflowfy.reflow_manager.database import SessionLocal
            db = SessionLocal()
            kafka_bootstrap_servers = os.getenv("KAFKA_BOOTSTRAP_SERVERS", "localhost:9092")
            kafka_topic = os.getenv("KAFKA_TOPIC", "reflow.jobs")
            max_jobs_per_second = float(os.getenv("MAX_JOBS_PER_SECOND", "100"))
            execution_mode = os.getenv("EXECUTION_MODE", "distributed")
            
            manager = ReflowManager(
                db_session=db,
                kafka_bootstrap_servers=kafka_bootstrap_servers,
                kafka_topic=kafka_topic,
                max_jobs_per_second=max_jobs_per_second,
                execution_mode=execution_mode,
            )
            return manager.pipeline_runner
        
        init_dlq_scheduler(pipeline_runner_factory)
        print("✅ DLQ Scheduler initialized")
    except Exception as e:
        print(f"⚠️ Failed to initialize DLQ scheduler: {e}")


async def _recover_interrupted_executions():
    """Find and resume any executions that were interrupted by a crash."""
    import asyncio
    from reflowfy.reflow_manager.database import SessionLocal
    
    db = SessionLocal()
    try:
        kafka_bootstrap_servers = os.getenv("KAFKA_BOOTSTRAP_SERVERS", "localhost:9092")
        kafka_topic = os.getenv("KAFKA_TOPIC", "reflow.jobs")
        max_jobs_per_second = float(os.getenv("MAX_JOBS_PER_SECOND", "100"))
        
        manager = ReflowManager(
            db_session=db,
            kafka_bootstrap_servers=kafka_bootstrap_servers,
            kafka_topic=kafka_topic,
            max_jobs_per_second=max_jobs_per_second,
        )
        
        # Find interrupted executions
        interrupted = manager.execution_manager.get_interrupted_executions()
        
        if not interrupted:
            print("  ✓ No interrupted executions found")
            return
        
        print(f"  Found {len(interrupted)} interrupted execution(s)")
        
        # Resume each in a background thread (don't block startup)
        for execution in interrupted:
            print(f"  → Scheduling resume for: {execution.execution_id}")
            # Use run_in_executor to avoid blocking the event loop
            asyncio.get_event_loop().run_in_executor(
                None,  # Default executor
                _resume_execution_sync,
                execution.execution_id,
            )
        
        print(f"  ✓ Scheduled {len(interrupted)} execution(s) for recovery")
    
    finally:
        db.close()


def _resume_execution_sync(execution_id: str):
    """Synchronously resume an execution (runs in thread pool)."""
    from reflowfy.reflow_manager.database import SessionLocal
    
    db = SessionLocal()
    try:
        kafka_bootstrap_servers = os.getenv("KAFKA_BOOTSTRAP_SERVERS", "localhost:9092")
        kafka_topic = os.getenv("KAFKA_TOPIC", "reflow.jobs")
        max_jobs_per_second = float(os.getenv("MAX_JOBS_PER_SECOND", "100"))
        
        manager = ReflowManager(
            db_session=db,
            kafka_bootstrap_servers=kafka_bootstrap_servers,
            kafka_topic=kafka_topic,
            max_jobs_per_second=max_jobs_per_second,
        )
        
        manager.pipeline_runner.resume_execution(execution_id)
    
    except Exception as e:
        import traceback
        print(f"❌ Failed to resume execution {execution_id}: {e}")
        traceback.print_exc()
    
    finally:
        db.close()



# Shutdown event
@app.on_event("shutdown")
async def shutdown_event():
    """Cleanup on shutdown."""
    print("\n🛑 Shutting down ReflowManager service...")
    stop_dlq_scheduler()
    print("✅ Shutdown complete")


# Main entry point
def main():
    """Run the FastAPI application."""
    import uvicorn
    
    host = os.getenv("HOST", "0.0.0.0")
    port = int(os.getenv("PORT", "8001"))
    
    print("=" * 60)
    print("🔧 ReflowManager Service")
    print("=" * 60)
    print(f"🌐 Server starting on http://{host}:{port}")
    print(f"📖 API docs at http://localhost:{port}/docs\n")
    
    uvicorn.run(app, host=host, port=port)


if __name__ == "__main__":
    main()
