from fastapi import FastAPI, Request, Response, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from contextlib import asynccontextmanager
import os
from pathlib import Path
import mimetypes

from config.settings import settings
from config.database import engine, Base
from api.routers import auth, users, events, albums, posts, vlogs, stats, admin, notifications, settings as settings_router, information, tickets
from utils.init_db import init_database
from utils.settings_service import SettingsService
from config.database import SessionLocal

# Create uploads directory if it doesn't exist
Path(settings.UPLOAD_PATH).mkdir(parents=True, exist_ok=True)

def init_default_settings():
    """Initialize default system settings."""
    db = SessionLocal()
    try:
        # Check if settings already exist
        from models.settings import SystemSettings
        existing_settings = db.query(SystemSettings).count()
        
        if existing_settings == 0:
            print("Initializing default system settings...")
            
            default_settings = [
                {
                    "key": "max_album_size_mb",
                    "value": "100",
                    "description": "Taille maximale des albums en MB",
                    "category": "uploads"
                },
                {
                    "key": "max_vlog_size_mb",
                    "value": "500",
                    "description": "Taille maximale des vlogs en MB",
                    "category": "uploads"
                },
                {
                    "key": "max_image_size_mb",
                    "value": "10",
                    "description": "Taille maximale des images en MB",
                    "category": "uploads"
                },
                {
                    "key": "max_video_size_mb",
                    "value": "100",
                    "description": "Taille maximale des vidéos en MB",
                    "category": "uploads"
                },
                {
                    "key": "max_media_per_album",
                    "value": "50",
                    "description": "Nombre maximum de médias par album",
                    "category": "uploads"
                },
                {
                    "key": "allowed_image_types",
                    "value": "image/jpeg,image/png,image/gif,image/webp",
                    "description": "Types d'images autorisés (séparés par des virgules)",
                    "category": "uploads"
                },
                {
                    "key": "allowed_video_types",
                    "value": "video/mp4,video/mpeg,video/quicktime,video/webm",
                    "description": "Types de vidéos autorisés (séparés par des virgules)",
                    "category": "uploads"
                },
                {
                    "key": "max_users",
                    "value": "50",
                    "description": "Nombre maximum d'utilisateurs",
                    "category": "general"
                },
                {
                    "key": "enable_registration",
                    "value": "true",
                    "description": "Autoriser les nouvelles inscriptions",
                    "category": "general"
                }
            ]
            
            for setting_data in default_settings:
                setting = SystemSettings(**setting_data)
                db.add(setting)
            
            db.commit()
            print(f"Created {len(default_settings)} default settings")
        else:
            print("System settings already exist, checking for missing settings...")
            
            # Check for missing settings and add them
            all_settings = [
                {
                    "key": "max_album_size_mb",
                    "value": "100",
                    "description": "Taille maximale des albums en MB",
                    "category": "uploads"
                },
                {
                    "key": "max_vlog_size_mb",
                    "value": "500",
                    "description": "Taille maximale des vlogs en MB",
                    "category": "uploads"
                },
                {
                    "key": "max_image_size_mb",
                    "value": "10",
                    "description": "Taille maximale des images en MB",
                    "category": "uploads"
                },
                {
                    "key": "max_video_size_mb",
                    "value": "100",
                    "description": "Taille maximale des vidéos en MB",
                    "category": "uploads"
                },
                {
                    "key": "max_media_per_album",
                    "value": "50",
                    "description": "Nombre maximum de médias par album",
                    "category": "uploads"
                },
                {
                    "key": "allowed_image_types",
                    "value": "image/jpeg,image/png,image/gif,image/webp",
                    "description": "Types d'images autorisés (séparés par des virgules)",
                    "category": "uploads"
                },
                {
                    "key": "allowed_video_types",
                    "value": "video/mp4,video/mpeg,video/quicktime,video/webm",
                    "description": "Types de vidéos autorisés (séparés par des virgules)",
                    "category": "uploads"
                },
                {
                    "key": "max_users",
                    "value": "50",
                    "description": "Nombre maximum d'utilisateurs",
                    "category": "general"
                },
                {
                    "key": "enable_registration",
                    "value": "true",
                    "description": "Autoriser les nouvelles inscriptions",
                    "category": "general"
                }
            ]
            
            added_count = 0
            for setting_data in all_settings:
                existing = db.query(SystemSettings).filter(SystemSettings.key == setting_data["key"]).first()
                if not existing:
                    setting = SystemSettings(**setting_data)
                    db.add(setting)
                    added_count += 1
            
            if added_count > 0:
                db.commit()
                print(f"Added {added_count} missing settings")
            else:
                print("All settings are already present")
            
    except Exception as e:
        print(f"Error initializing settings: {e}")
        db.rollback()
    finally:
        db.close()

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup
    print("Starting LeDiscord backend...")
    # Create tables
    Base.metadata.create_all(bind=engine)
    # Initialize database with admin user
    init_database()
    # Initialize default settings
    init_default_settings()
    yield
    # Shutdown
    print("Shutting down LeDiscord backend...")

app = FastAPI(
    title="LeDiscord API",
    description="API pour la plateforme communautaire LeDiscord",
    version="1.0.0",
    lifespan=lifespan
)

# Configure CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.CORS_ORIGINS_LIST,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
    expose_headers=["Content-Range", "Accept-Ranges"],
)

# Endpoint personnalisé pour servir les vidéos avec support Range
@app.get("/uploads/{file_path:path}")
async def serve_media_with_range(request: Request, file_path: str):
    """
    Serve media files with proper Range request support for video scrubbing.
    """
    file_full_path = Path(settings.UPLOAD_PATH) / file_path
    
    # Vérifier que le fichier existe
    if not file_full_path.exists() or not file_full_path.is_file():
        raise HTTPException(status_code=404, detail="File not found")
    
    # Vérifier que le fichier est dans le répertoire uploads (sécurité)
    try:
        file_full_path.resolve().relative_to(Path(settings.UPLOAD_PATH).resolve())
    except ValueError:
        raise HTTPException(status_code=403, detail="Access denied")
    
    # Obtenir la taille du fichier
    file_size = file_full_path.stat().st_size
    
    # Déterminer le content type
    content_type, _ = mimetypes.guess_type(str(file_full_path))
    if not content_type:
        content_type = "application/octet-stream"
    
    # Gérer les requêtes Range
    range_header = request.headers.get("Range")
    
    if range_header:
        # Parser le header Range (format: bytes=start-end)
        range_match = range_header.replace("bytes=", "").split("-")
        start = int(range_match[0]) if range_match[0] else 0
        end = int(range_match[1]) if range_match[1] and range_match[1] else file_size - 1
        
        # Valider la plage
        if start >= file_size or end >= file_size or start > end:
            return Response(
                status_code=416,
                headers={
                    "Content-Range": f"bytes */{file_size}",
                    "Accept-Ranges": "bytes"
                }
            )
        
        # Lire la plage demandée
        chunk_size = end - start + 1
        with open(file_full_path, "rb") as f:
            f.seek(start)
            chunk = f.read(chunk_size)
        
        # Retourner la réponse 206 Partial Content
        return Response(
            content=chunk,
            status_code=206,
            headers={
                "Content-Range": f"bytes {start}-{end}/{file_size}",
                "Accept-Ranges": "bytes",
                "Content-Length": str(chunk_size),
                "Content-Type": content_type,
            },
            media_type=content_type
        )
    else:
        # Pas de Range header, retourner le fichier complet
        with open(file_full_path, "rb") as f:
            content = f.read()
        
        return Response(
            content=content,
            headers={
                "Accept-Ranges": "bytes",
                "Content-Length": str(file_size),
                "Content-Type": content_type,
            },
            media_type=content_type
        )

# Note: StaticFiles mount retiré car notre endpoint personnalisé gère tous les fichiers
# avec support Range pour permettre le scrubbing vidéo

# Include routers
app.include_router(auth.router, prefix="/api/auth", tags=["Authentication"])
app.include_router(users.router, prefix="/api/users", tags=["Users"])
app.include_router(events.router, prefix="/api/events", tags=["Events"])
app.include_router(albums.router, prefix="/api/albums", tags=["Albums"])
app.include_router(posts.router, prefix="/api/posts", tags=["Posts"])
app.include_router(vlogs.router, prefix="/api/vlogs", tags=["Vlogs"])
app.include_router(stats.router, prefix="/api/stats", tags=["Statistics"])
app.include_router(admin.router, prefix="/api/admin", tags=["Admin"])
app.include_router(notifications.router, prefix="/api/notifications", tags=["Notifications"])
app.include_router(settings_router.router, prefix="/api/settings", tags=["Settings"])
app.include_router(information.router, prefix="/api/information", tags=["Information"])
app.include_router(tickets.router, prefix="/api/tickets", tags=["Tickets"])

@app.get("/")
async def root():
    return {
        "message": "Bienvenue sur LeDiscord API",
        "version": "1.0.0",
        "docs": "/docs"
    }

@app.get("/health")
async def health_check():
    return {"status": "healthy"}
