# Copy the content from the main_app_file artifact above
# src/main.py
"""
FastAPI application entry point for the self-improving code generator
"""

import logging
import asyncio
import time
from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException, BackgroundTasks, Depends
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import OperationalError

from .utils.config import get_settings, validate_configuration
from .models.database_models import Base
from .api.routes import router
from .services.orchestrator import SelfImprovingCodeGenerator

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(levelname)s | %(name)s | %(message)s"
)
logger = logging.getLogger(__name__)

# Global variables
generator: SelfImprovingCodeGenerator = None
engine = None
SessionLocal = None

async def wait_for_database(database_url: str, max_retries: int = 30, delay: float = 2.0):
    """Wait for database to be available with retry logic"""
    for attempt in range(max_retries):
        try:
            logger.info(f"Attempting database connection (attempt {attempt + 1}/{max_retries})")
            test_engine = create_engine(database_url)
            
            # Test the connection
            with test_engine.connect() as conn:
                conn.execute(text("SELECT 1"))
            
            logger.info("✅ Database connection successful")
            test_engine.dispose()
            return True
            
        except OperationalError as e:
            if attempt < max_retries - 1:
                logger.warning(f"Database connection failed (attempt {attempt + 1}): {e}")
                logger.info(f"Retrying in {delay} seconds...")
                await asyncio.sleep(delay)
            else:
                logger.error(f"Failed to connect to database after {max_retries} attempts: {e}")
                raise
        except Exception as e:
            logger.error(f"Unexpected error connecting to database: {e}")
            raise
    
    return False

@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan events"""
    global generator, engine, SessionLocal
    
    try:
        # Validate configuration
        validate_configuration()
        settings = get_settings()
        
        logger.info("🚀 Starting Self-Improving Code Generator")
        
        # Wait for database to be available
        await wait_for_database(settings.database_url)
        
        # Initialize database
        engine = create_engine(settings.database_url)
        SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
        
        # Create database tables
        Base.metadata.create_all(bind=engine)
        logger.info("✅ Database initialized")
        
        # Initialize the generator
        generator = SelfImprovingCodeGenerator(
            claude_api_key=settings.claude_api_key,
            database_url=settings.database_url
        )
        logger.info("✅ Self-improving generator initialized")
        
        yield
        
    except Exception as e:
        logger.error(f"❌ Failed to start application: {e}")
        raise
    finally:
        logger.info("🛑 Shutting down Self-Improving Code Generator")
        if engine:
            engine.dispose()

# Create FastAPI app
app = FastAPI(
    title="Self-Improving Code Generator",
    description="AI-powered code generation with continuous quality improvement",
    version="1.0.0",
    lifespan=lifespan
)

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

# Include API routes
app.include_router(router, prefix="/api/v1")

# Dependency to get generator instance
def get_generator() -> SelfImprovingCodeGenerator:
    """Get the global generator instance"""
    if generator is None:
        raise HTTPException(status_code=500, detail="Generator not initialized")
    return generator

# Dependency to get database session
def get_db():
    """Get database session"""
    if SessionLocal is None:
        raise HTTPException(status_code=500, detail="Database not initialized")
    
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/")
async def root():
    """Root endpoint"""
    return {
        "service": "Self-Improving Code Generator",
        "version": "1.0.0",
        "status": "running",
        "capabilities": [
            "Technology-agnostic analysis",
            "Progressive enhancement",
            "Learning from user preferences",
            "Real-time improvement tracking",
            "Multi-language support"
        ]
    }

@app.get("/health")
async def health_check():
    """Health check endpoint"""
    try:
        settings = get_settings()
        
        # Test database connection
        db_status = "disconnected"
        if engine:
            try:
                with engine.connect() as conn:
                    conn.execute(text("SELECT 1"))
                db_status = "connected"
            except Exception as e:
                logger.warning(f"Database health check failed: {e}")
                db_status = "error"
        
        health_status = {
            "status": "healthy",
            "service": "Self-Improving Code Generator",
            "version": "1.0.0",
            "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
            "dependencies": {
                "database": db_status,
                "claude_api": "configured" if settings.claude_api_key else "not_configured",
                "generator": "initialized" if generator else "not_initialized"
            }
        }
        
        # Check if all dependencies are healthy
        all_healthy = (
            health_status["dependencies"]["database"] == "connected" and
            health_status["dependencies"]["claude_api"] == "configured" and
            health_status["dependencies"]["generator"] == "initialized"
        )
        
        if not all_healthy:
            health_status["status"] = "unhealthy"
        
        return health_status
        
    except Exception as e:
        logger.error(f"Health check failed: {e}")
        return {
            "status": "error",
            "service": "Self-Improving Code Generator",
            "version": "1.0.0",
            "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
            "error": str(e)
        }

if __name__ == "__main__":
    import uvicorn
    settings = get_settings()
    
    uvicorn.run(
        "src.main:app",
        host=settings.service_host,
        port=settings.service_port,
        reload=True,
        log_level=settings.log_level.lower()
    )