from fastapi import APIRouter, HTTPException, status, Depends
from bson import ObjectId
import pymongo
from datetime import datetime, timedelta

import app.config as config
from app.models import User, HTTPError
from app.models.config import SystemConfig, DBConfig
from app.routes.auth import users_collection
from app.routes.utils import get_admin_user
from app.dto import UserAdminDTO

# Database setup
client = pymongo.MongoClient(config.MONGODB_URL, username=config.MONGODB_USERNAME, password=config.MONGODB_PASSWORD)
db = client[config.MONGODB_DATABASE]

pins_collection = db["pins"]
images_collection = db["images"]
friends_collection = db["friends"]
pin_permissions_collection = db["pin_permissions"]
config_collection = db["config"]

admin_router = APIRouter(
    prefix="/admin",
    tags=["Admin"]
)

def serialize_mongo_doc(doc):
    """Convertit un document MongoDB en dictionnaire sérialisable"""
    if doc is None:
        return None
    
    result = {}
    for key, value in doc.items():
        if isinstance(value, ObjectId):
            result[key] = str(value)
        elif isinstance(value, dict):
            result[key] = serialize_mongo_doc(value)
        elif isinstance(value, list):
            result[key] = [serialize_mongo_doc(item) if isinstance(item, dict) else str(item) if isinstance(item, ObjectId) else item for item in value]
        else:
            result[key] = value
    return result

def load_config():
    """Charge la configuration depuis la base de données ou utilise les valeurs par défaut"""
    db_config = config_collection.find_one({"_id": "system_config"})
    
    if db_config:
        # Mettre à jour les variables de configuration
        config.MAX_IMAGE_SIZE = db_config["config"]["max_image_size"]
        config.MAX_IMAGES_PER_PIN = db_config["config"]["max_images_per_pin"]
        config.MAX_IMAGES_PER_USER = db_config["config"]["max_images_per_user"]
        config.ALLOWED_MIME_TYPES = db_config["config"]["allowed_image_types"]
        config.MAX_PINS_PER_USER = db_config["config"]["max_pins_per_user"]
        config.MAX_FRIENDS_PER_USER = db_config["config"]["max_friends_per_user"]
    else:
        # Créer la configuration par défaut dans la base de données
        default_config = DBConfig(
            config=SystemConfig(**config.DEFAULT_CONFIG),
            updated_at=datetime.now(),
            updated_by="system"
        )
        config_collection.insert_one({
            "_id": "system_config",
            **default_config.model_dump()
        })

# Charger la configuration au démarrage
load_config()

@admin_router.get(
    path="/stats",
    responses={401: {"model": HTTPError}, 403: {"model": HTTPError}}
)
async def get_stats(admin_user: User = Depends(get_admin_user)):
    # Statistiques générales
    total_users = users_collection.count_documents({})
    total_pins = pins_collection.count_documents({})
    total_images = images_collection.count_documents({})
    total_friends = friends_collection.count_documents({"status": "accepted"})
    
    # Statistiques des 30 derniers jours
    thirty_days_ago = datetime.now() - timedelta(days=30)
    new_users = users_collection.count_documents({
        "created_at": {"$gte": thirty_days_ago}
    })
    new_pins = pins_collection.count_documents({
        "created_at": {"$gte": thirty_days_ago}
    })
    new_images = images_collection.count_documents({
        "metadata.created_at": {"$gte": thirty_days_ago.isoformat()}
    })
    
    # Top utilisateurs
    top_users = list(users_collection.aggregate([
        {"$lookup": {
            "from": "pins",
            "let": { "user_id": { "$toString": "$_id" } },
            "pipeline": [
                { "$match": { "$expr": { "$eq": ["$user_id", "$$user_id"] } } }
            ],
            "as": "pins"
        }},
        {"$project": {
            "username": 1,
            "pin_count": {"$size": "$pins"}
        }},
        {"$sort": {"pin_count": -1}},
        {"$limit": 5}
    ]))
    
    # Top pins (les plus partagés)
    top_pins = list(pin_permissions_collection.aggregate([
        {"$group": {
            "_id": "$pin_id",
            "share_count": {"$sum": 1}
        }},
        {"$sort": {"share_count": -1}},
        {"$limit": 5},
        {"$lookup": {
            "from": "pins",
            "localField": "_id",
            "foreignField": "_id",
            "as": "pin_info"
        }},
        {"$unwind": "$pin_info"},
        {"$project": {
            "pin_id": "$_id",
            "share_count": 1,
            "title": "$pin_info.title"
        }}
    ]))
    
    # Statistiques de stockage
    total_storage = sum(
        image["metadata"]["size"] 
        for image in images_collection.find({}, {"metadata.size": 1})
    )
    
    return {
        "general": {
            "total_users": total_users,
            "total_pins": total_pins,
            "total_images": total_images,
            "total_friends": total_friends,
            "total_storage_bytes": total_storage
        },
        "last_30_days": {
            "new_users": new_users,
            "new_pins": new_pins,
            "new_images": new_images
        },
        "top_users": [serialize_mongo_doc(user) for user in top_users],
        "top_shared_pins": [serialize_mongo_doc(pin) for pin in top_pins]
    }

@admin_router.get(
    path="/config",
    response_model=SystemConfig,
    responses={401: {"model": HTTPError}, 403: {"model": HTTPError}}
)
async def get_config(admin_user: User = Depends(get_admin_user)):
    db_config = config_collection.find_one({"_id": "system_config"})
    if not db_config:
        return SystemConfig(**config.DEFAULT_CONFIG)
    return SystemConfig(**db_config["config"])

@admin_router.patch(
    path="/config",
    response_model=SystemConfig,
    responses={401: {"model": HTTPError}, 403: {"model": HTTPError}}
)
async def update_config(
    new_config: SystemConfig,
    admin_user: User = Depends(get_admin_user)
):
    # Mettre à jour la configuration en base de données
    db_config = DBConfig(
        config=new_config,
        updated_at=datetime.now(),
        updated_by=admin_user.uid
    )
    
    config_collection.update_one(
        {"_id": "system_config"},
        {"$set": db_config.model_dump()},
        upsert=True
    )
    
    # Mettre à jour les variables de configuration
    config.MAX_IMAGE_SIZE = new_config.max_image_size
    config.MAX_IMAGES_PER_PIN = new_config.max_images_per_pin
    config.MAX_IMAGES_PER_USER = new_config.max_images_per_user
    config.ALLOWED_MIME_TYPES = new_config.allowed_image_types
    config.MAX_PINS_PER_USER = new_config.max_pins_per_user
    config.MAX_FRIENDS_PER_USER = new_config.max_friends_per_user
    
    return new_config 

@admin_router.get(
    path="/users",
    responses={401: {"model": HTTPError}, 403: {"model": HTTPError}},
    response_model=list[UserAdminDTO]
)
async def list_users(admin_user: User = Depends(get_admin_user)):
    """Liste tous les utilisateurs (sans le mot de passe) - Route admin uniquement"""
    users = users_collection.find({}, {"password": 0})  # Exclure le mot de passe
    users_list = []

    for user in users:
        user["uid"] = str(user["_id"])
        user = UserAdminDTO(**user)
        users_list.append(user)

    return users_list

@admin_router.delete(
    path="/user/{uid}",
    responses={401: {"model": HTTPError}, 403: {"model": HTTPError}, 404: {"model": HTTPError}, 400: {"model": HTTPError}}
)
async def delete_user(uid: str, admin_user: User = Depends(get_admin_user)):
    try:
        ObjectId(uid)
    except:
        raise HTTPException(status_code=400, detail="UID invalide")
    
    user = users_collection.find_one({"_id": ObjectId(uid)})
    if not user:
        raise HTTPException(status_code=404, detail="Utilisateur non trouvé")
    users_collection.delete_one({"_id": ObjectId(uid)})

    return {"message": "Utilisateur supprimé avec succès"}
