"""
Simple app creation utilities - LangChain-style ease of use
"""

from typing import List, Optional, Type
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from apex.core.config import get_settings
from apex.infrastructure.database import engine
from apex.infrastructure.database.base import Base
from apex.api.v1 import (
    auth_router,
    users_router,
    organizations_router,
    roles_router,
    permissions_router,
    modules_router,
    settings_router,
    payments_router,
)


def create_app(
    title: Optional[str] = None,
    description: Optional[str] = None,
    version: Optional[str] = None,
    models: Optional[List[Type]] = None,
    enable_auth: bool = True,
    enable_users: bool = True,
    enable_organizations: bool = True,
    enable_roles: bool = True,
    enable_permissions: bool = True,
    enable_modules: bool = True,
    enable_settings: bool = True,
    enable_payments: bool = True,
    enable_cors: bool = True,
    # Endpoint prefixes
    auth_prefix: str = "/api/auth",
    users_prefix: str = "/api/users",
    organizations_prefix: str = "/api/organizations",
    roles_prefix: str = "/api/roles",
    permissions_prefix: str = "/api/permissions",
    modules_prefix: str = "/api/modules",
    settings_prefix: str = "/api/settings",
    payments_prefix: str = "/api/payments",
    **kwargs
) -> FastAPI:
    """
    Create a FastAPI app with all Apex routes configured.
    
    Args:
        title: Application title
        description: Application description
        version: Application version
        models: List of SQLAlchemy models to register
        enable_auth: Enable authentication routes
        enable_users: Enable user management routes
        enable_organizations: Enable organization routes
        enable_roles: Enable role management routes
        enable_permissions: Enable permission routes
        enable_modules: Enable module/feature flag routes
        enable_settings: Enable settings routes
        enable_payments: Enable PayPal payment routes
        enable_cors: Enable CORS middleware
        **kwargs: Additional FastAPI configuration
    
    Returns:
        Configured FastAPI application
    
    Example:
        >>> from apex import create_app
        >>> from models import User, Organization
        >>> 
        >>> app = create_app(
        ...     title="My SaaS App",
        ...     models=[User, Organization]
        ... )
    """
    settings = get_settings()
    
    # Create FastAPI app
    app = FastAPI(
        title=title or settings.APP_NAME,
        description=description or "Built with Apex SaaS Framework",
        version=version or settings.APP_VERSION,
        **kwargs
    )
    
    # Add CORS middleware
    if enable_cors:
        app.add_middleware(
            CORSMiddleware,
            allow_origins=settings.CORS_ORIGINS,
            allow_credentials=settings.CORS_ALLOW_CREDENTIALS,
            allow_methods=settings.CORS_ALLOW_METHODS,
            allow_headers=settings.CORS_ALLOW_HEADERS,
        )
    
    # Include routers based on flags with configurable prefixes
    if enable_auth:
        app.include_router(auth_router, prefix=auth_prefix, tags=["Authentication"])
    
    if enable_users:
        app.include_router(users_router, prefix=users_prefix, tags=["Users"])
    
    if enable_organizations:
        app.include_router(organizations_router, prefix=organizations_prefix, tags=["Organizations"])
    
    if enable_roles:
        app.include_router(roles_router, prefix=roles_prefix, tags=["Roles"])
    
    if enable_permissions:
        app.include_router(permissions_router, prefix=permissions_prefix, tags=["Permissions"])
    
    if enable_modules:
        app.include_router(modules_router, prefix=modules_prefix, tags=["Modules"])
    
    if enable_settings:
        app.include_router(settings_router, prefix=settings_prefix, tags=["Settings"])
    
    if enable_payments:
        app.include_router(payments_router, prefix=payments_prefix, tags=["Payments"])
    
    # Add root endpoint
    @app.get("/", tags=["Root"])
    async def root():
        return {
            "message": f"Welcome to {title or settings.APP_NAME}",
            "version": version or settings.APP_VERSION,
            "docs": "/docs",
            "redoc": "/redoc"
        }
    
    # Add health check
    @app.get("/health", tags=["Health"])
    async def health_check():
        return {"status": "healthy"}
    
    return app


async def init_database(app: Optional[FastAPI] = None, echo: bool = False, show_tables: bool = True):
    """
    Initialize database and create all tables.
    
    Args:
        app: FastAPI application (optional)
        echo: Echo SQL statements (for debugging)
        show_tables: Show created tables in console
    
    Example:
        >>> await init_database()
    """
    import sys
    from apex.core.config import get_settings
    
    settings = get_settings()
    
    # Show database connection info
    db_url = str(settings.DATABASE_URL)
    # Mask password in URL
    if "@" in db_url:
        parts = db_url.split("@")
        if "://" in parts[0]:
            protocol_user = parts[0].split("://")
            if ":" in protocol_user[1]:
                user_pass = protocol_user[1].split(":")
                masked_url = f"{protocol_user[0]}://{user_pass[0]}:****@{parts[1]}"
            else:
                masked_url = db_url
        else:
            masked_url = db_url
    else:
        masked_url = db_url
    
    import sys
    
    sys.stdout.write("🔌 Connecting to database...\n")
    sys.stdout.write(f"   Database URL: {masked_url}\n")
    sys.stdout.flush()
    
    try:
        from sqlalchemy import text
        
        async with engine.begin() as conn:
            # Get all table names before creation
            existing_tables = set()
            try:
                result = await conn.execute(
                    text("SELECT tablename FROM pg_tables WHERE schemaname = 'public'")
                )
                rows = result.fetchall()
                existing_tables = {row[0] for row in rows} if rows else set()
            except Exception:
                pass  # If we can't query, just continue
            
            # Create all tables
            await conn.run_sync(Base.metadata.create_all)
            
            # Get all table names after creation
            try:
                result = await conn.execute(
                    text("SELECT tablename FROM pg_tables WHERE schemaname = 'public'")
                )
                rows = result.fetchall()
                all_tables = {row[0] for row in rows} if rows else set()
            except Exception:
                all_tables = set()
            
            new_tables = all_tables - existing_tables
            
            sys.stdout.write("✅ Database connected successfully!\n")
            sys.stdout.flush()
            
            if show_tables:
                if new_tables:
                    sys.stdout.write(f"\n📊 Created {len(new_tables)} table(s):\n")
                    for table in sorted(new_tables):
                        sys.stdout.write(f"   ✓ {table}\n")
                
                if existing_tables:
                    sys.stdout.write(f"\n📋 Existing tables ({len(existing_tables)}):\n")
                    for table in sorted(existing_tables):
                        sys.stdout.write(f"   • {table}\n")
                
                if not all_tables:
                    sys.stdout.write("\n⚠️  No tables found. Make sure models are properly imported.\n")
                
                sys.stdout.write("\n")  # Empty line for readability
                sys.stdout.flush()
                
    except Exception as e:
        sys.stdout.write(f"❌ Database connection failed: {e}\n")
        sys.stdout.flush()
        raise


class ApexConfig:
    """Configuration for Apex application"""
    
    def __init__(
        self,
        title: Optional[str] = None,
        description: Optional[str] = None,
        version: Optional[str] = None,
        enable_auth: bool = True,
        enable_users: bool = True,
        enable_organizations: bool = True,
        enable_roles: bool = True,
        enable_permissions: bool = True,
        enable_modules: bool = True,
        enable_settings: bool = True,
        enable_payments: bool = True,
        enable_cors: bool = True,
        auto_create_tables: bool = True,
        # Endpoint prefixes - customize as needed
        auth_prefix: str = "/api/auth",
        users_prefix: str = "/api/users",
        organizations_prefix: str = "/api/organizations",
        roles_prefix: str = "/api/roles",
        permissions_prefix: str = "/api/permissions",
        modules_prefix: str = "/api/modules",
        settings_prefix: str = "/api/settings",
        payments_prefix: str = "/api/payments",
    ):
        self.title = title
        self.description = description
        self.version = version
        self.enable_auth = enable_auth
        self.enable_users = enable_users
        self.enable_organizations = enable_organizations
        self.enable_roles = enable_roles
        self.enable_permissions = enable_permissions
        self.enable_modules = enable_modules
        self.enable_settings = enable_settings
        self.enable_payments = enable_payments
        self.enable_cors = enable_cors
        self.auto_create_tables = auto_create_tables
        # Endpoint prefixes
        self.auth_prefix = auth_prefix
        self.users_prefix = users_prefix
        self.organizations_prefix = organizations_prefix
        self.roles_prefix = roles_prefix
        self.permissions_prefix = permissions_prefix
        self.modules_prefix = modules_prefix
        self.settings_prefix = settings_prefix
        self.payments_prefix = payments_prefix


class Apex:
    """
    Main Apex framework class - Simple, LangChain-style API.
    
    Example 1 - Minimal:
        >>> from apex import Apex
        >>> app = Apex().app
    
    Example 2 - With models:
        >>> from apex import Apex
        >>> from models import User, Organization
        >>> 
        >>> app = Apex(models=[User, Organization]).app
    
    Example 3 - With configuration:
        >>> from apex import Apex, ApexConfig
        >>> 
        >>> config = ApexConfig(
        ...     title="My SaaS App",
        ...     enable_payments=True
        ... )
        >>> app = Apex(config=config).app
    
    Example 4 - Fluent API:
        >>> app = (
        ...     Apex()
        ...     .with_auth()
        ...     .with_payments()
        ...     .build()
        ... )
    """
    
    def __init__(
        self,
        models: Optional[List[Type]] = None,
        config: Optional[ApexConfig] = None,
        title: Optional[str] = None,
        **kwargs
    ):
        """
        Initialize Apex application.
        
        Args:
            models: List of SQLAlchemy models to register
            config: ApexConfig instance
            title: Application title
            **kwargs: Additional configuration passed to create_app
        """
        self.models = models or []
        self.config = config or ApexConfig()
        
        # Override config with direct parameters
        if title:
            self.config.title = title
        
        # Create the FastAPI app
        self.app = create_app(
            title=self.config.title,
            description=self.config.description,
            version=self.config.version,
            models=self.models,
            enable_auth=self.config.enable_auth,
            enable_users=self.config.enable_users,
            enable_organizations=self.config.enable_organizations,
            enable_roles=self.config.enable_roles,
            enable_permissions=self.config.enable_permissions,
            enable_modules=self.config.enable_modules,
            enable_settings=self.config.enable_settings,
            enable_payments=self.config.enable_payments,
            enable_cors=self.config.enable_cors,
            auth_prefix=self.config.auth_prefix,
            users_prefix=self.config.users_prefix,
            organizations_prefix=self.config.organizations_prefix,
            roles_prefix=self.config.roles_prefix,
            permissions_prefix=self.config.permissions_prefix,
            modules_prefix=self.config.modules_prefix,
            settings_prefix=self.config.settings_prefix,
            payments_prefix=self.config.payments_prefix,
            **kwargs
        )
        
        # Auto-create tables on startup if enabled
        if self.config.auto_create_tables:
            @self.app.on_event("startup")
            async def startup_event():
                await init_database(self.app, show_tables=True)
    
    def with_auth(self, enabled: bool = True):
        """Enable authentication routes (fluent API)"""
        self.config.enable_auth = enabled
        return self
    
    def with_users(self, enabled: bool = True):
        """Enable user management routes (fluent API)"""
        self.config.enable_users = enabled
        return self
    
    def with_organizations(self, enabled: bool = True):
        """Enable organization routes (fluent API)"""
        self.config.enable_organizations = enabled
        return self
    
    def with_roles(self, enabled: bool = True):
        """Enable role management routes (fluent API)"""
        self.config.enable_roles = enabled
        return self
    
    def with_permissions(self, enabled: bool = True):
        """Enable permission routes (fluent API)"""
        self.config.enable_permissions = enabled
        return self
    
    def with_modules(self, enabled: bool = True):
        """Enable module/feature flag routes (fluent API)"""
        self.config.enable_modules = enabled
        return self
    
    def with_settings(self, enabled: bool = True):
        """Enable settings routes (fluent API)"""
        self.config.enable_settings = enabled
        return self
    
    def with_payments(self, enabled: bool = True):
        """Enable PayPal payment routes (fluent API)"""
        self.config.enable_payments = enabled
        return self
    
    def with_cors(self, enabled: bool = True):
        """Enable CORS middleware (fluent API)"""
        self.config.enable_cors = enabled
        return self
    
    def build(self) -> FastAPI:
        """Build and return the FastAPI app (fluent API)"""
        return self.app

