"""
Dynamic CORS Manager - Load domains from database
No code changes needed for new domains
"""
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
from typing import List, Set

from src.database.connection import get_db
from src.database.api_key_models import AllowedDomain
from src.utils.logger import get_logger

logger = get_logger(__name__)


class DynamicCORSManager:
    """
    Manage CORS dynamically from database
    Auto-register new domains on first use
    """
    
    def __init__(self):
        self.allowed_origins: Set[str] = set()
        self.last_refresh = None
    
    def load_domains_from_db(self, db: Session) -> List[str]:
        """
        Load all active domains from database
        Called on startup and can be refreshed
        """
        try:
            domains = db.query(AllowedDomain).filter(
                AllowedDomain.is_active == True
            ).all()
            
            self.allowed_origins = {domain.domain for domain in domains}
            
            logger.info(f"Loaded {len(self.allowed_origins)} allowed domains from database")
            for domain in sorted(self.allowed_origins):
                logger.info(f"   - {domain}")
            
            return list(self.allowed_origins)
        
        except Exception as e:
            logger.error(f"Failed to load domains from database: {e}")
            # Fallback to localhost for development
            return ["http://localhost:3000", "http://localhost:8080"]
    
    def is_domain_allowed(self, origin: str) -> bool:
        """Check if domain is in allowed list"""
        return origin in self.allowed_origins
    
    def auto_register_domain(
        self, 
        db: Session, 
        origin: str, 
        client_id: str,
        description: str = "Auto-registered on first API call"
    ) -> bool:
        """
        Auto-register new domain when valid API key is used
        This makes the system plug-and-play
        """
        try:
            # Check if domain already exists
            existing = db.query(AllowedDomain).filter(
                AllowedDomain.domain == origin
            ).first()
            
            if existing:
                # Update last seen
                existing.last_seen_at = datetime.utcnow()
                existing.total_requests += 1
                db.commit()
                return True
            
            # Add new domain
            new_domain = AllowedDomain(
                domain=origin,
                client_id=client_id,
                auto_registered=True,
                description=description
            )
            
            db.add(new_domain)
            db.commit()
            
            # Add to in-memory cache
            self.allowed_origins.add(origin)
            
            logger.info(f"Auto-registered new domain: {origin} (client: {client_id})")
            return True
        
        except Exception as e:
            logger.error(f"Failed to auto-register domain {origin}: {e}")
            return False
    
    def refresh_domains(self, db: Session):
        """
        Refresh domains from database without restarting server
        Can be called via admin API endpoint
        """
        self.load_domains_from_db(db)
        logger.info("Domains refreshed from database")


# Global instance
cors_manager = DynamicCORSManager()


def configure_dynamic_cors(app: FastAPI):
    """
    Configure CORS with database-driven origins
    Loads on startup, no hardcoded domains
    """
    
    # Load domains from database on startup
    db = next(get_db())
    allowed_origins = cors_manager.load_domains_from_db(db)
    
    # Add wildcard for development (optional, can remove for production)
    # allowed_origins.append("*")  # WARNING: Only for testing!
    
    app.add_middleware(
        CORSMiddleware,
        allow_origins=allowed_origins if allowed_origins else ["*"],
        allow_credentials=True,
        allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
        allow_headers=[
            "Content-Type",
            "Authorization",
            "x-myrx-api_key",
            "x-myrx-request_id",
        ],
        expose_headers=[
            "x-myrx-request_id",
            "x-response-time"
        ]
    )
    
    logger.info(f"CORS configured with {len(allowed_origins)} domains")
    
    return cors_manager


# Middleware to auto-register domains
async def auto_register_origin_middleware(request: Request, call_next):
    """
    Middleware to auto-register new origins from authenticated requests
    """
    response = await call_next(request)
    
    # If request was successful and has origin header
    origin = request.headers.get("origin")
    if origin and response.status_code == 200:
        # Check if this is an authenticated request
        api_key = request.headers.get("x-myrx-api_key")
        if api_key:
            # Auto-register in background (don't block response)
            try:
                db = next(get_db())
                # Extract client_id from the validated request
                # (This will be set by the auth middleware)
                client_id = getattr(request.state, "client_id", "unknown")
                
                if client_id != "unknown":
                    cors_manager.auto_register_domain(db, origin, client_id)
            except Exception as e:
                logger.error(f"Failed to auto-register origin: {e}")
    
    return response
