from fastapi import APIRouter, HTTPException, Depends, status, UploadFile, File, Request, Form
from fastapi.responses import JSONResponse, FileResponse
from pydantic import BaseModel
from typing import Optional, List, Dict, Any, Union
from pymongo import MongoClient
from bson import ObjectId
import shutil
import os
import pathlib
from datetime import datetime
from src.core.config import settings
from src.utils.auth import verify_password, create_access_token, get_password_hash
# Import service accessor
from src.api.chat import get_assistant_service

router = APIRouter(prefix="/admin", tags=["Admin"])

# MongoDB connection
client = MongoClient(settings.MONGODB_URI)
db = client[settings.DB_NAME]
admins_collection = db["admins"]
#print(f"DEBUG: MongoDB Connected. DB: {settings.DB_NAME}")
#  Models 
class LoginRequest(BaseModel):
    email: str
    password: str

class PermissionBase(BaseModel):
    name: str 
    code: str 
    description: Optional[str] = None

class RolePermission(BaseModel):
    module_id: Optional[str] = None # Made optional for input
    module_name: str 
    view: bool = False
    add: bool = False
    edit: bool = False
    delete: bool = False

class RoleBase(BaseModel):
    role: str 
    description: Optional[str] = None # Added description field
    is_delete: bool = False
    permission: List[RolePermission]

class PermissionUpdate(BaseModel):
    name: Optional[str] = None
    code: Optional[str] = None
    description: Optional[str] = None

#  Permission APIs 

@router.post("/permissions", status_code=201)
async def create_permission(data: PermissionBase):
    doc = data.dict()
    result = db["permissions"].insert_one(doc)
    
    # Manual response construction
    response_data = {
        "id": str(result.inserted_id),
        "name": doc.get("name"),
        "code": doc.get("code"),
        "description": doc.get("description")
    }
    
    return {
        "data": {
            "status": 201,
            "message": "Permission created successfully.",
            "permission_details": response_data
        }
    }

@router.get("/permissions")
async def get_all_permissions():
    perms = []
    for p in db["permissions"].find():
        perms.append({
            "id": str(p["_id"]),
            "name": p.get("name"),
            "code": p.get("code"),
            "description": p.get("description")
        })
        
    return {
        "data": {
            "status": 200,
            "message": "Permissions retrieved successfully.",
            "permissions": perms
        }
    }

@router.get("/permissions/{id}")
async def get_permission_by_id(id: str):
    perm = db["permissions"].find_one({"_id": ObjectId(id)})
    if not perm:
        raise HTTPException(status_code=404, detail="Permission not found")
    
    perm_data = {
        "id": str(perm["_id"]),
        "name": perm.get("name"),
        "code": perm.get("code"),
        "description": perm.get("description")
    }

    return {
        "data": {
            "status": 200,
            "message": "Permission retrieved successfully.",
            "permission": perm_data
        }
    }

@router.put("/permissions/{id}")
async def edit_permission(id: str, data: PermissionUpdate):
    update_data = {k: v for k, v in data.dict().items() if v is not None}
    db["permissions"].update_one({"_id": ObjectId(id)}, {"$set": update_data})
    perm = db["permissions"].find_one({"_id": ObjectId(id)})
    
    perm_data = {
        "id": str(perm["_id"]),
        "name": perm.get("name"),
        "code": perm.get("code"),
        "description": perm.get("description")
    }
    
    return {
        "data": {
            "status": 200,
            "message": "Permission updated successfully.",
            "permission": perm_data
        }
    }


@router.delete("/permissions/{id}")
async def delete_permission(id: str):
    result = db["permissions"].delete_one({"_id": ObjectId(id)})
    if result.deleted_count == 0:
        raise HTTPException(status_code=404, detail="Permission not found")
    return {
        "data": {
            "status": 200,
            "message": "Permission deleted successfully.",
            "result": None
        }
    }

#  Role APIs 

@router.post("/roles", status_code=201)
async def create_role(data: RoleBase):
    doc = data.dict()
    
    # Auto-fetch module_id if missing
    for p in doc["permission"]:
        if not p.get("module_id"):
            # Try to find permission by code (module_name)
            perm_doc = db["permissions"].find_one({"code": p["module_name"]})
            if perm_doc:
                p["module_id"] = str(perm_doc["_id"])
            else:
                # If module doesn't exist (like 'test_bhavya'), keep it as None or generate ID? 
                # Keeping it empty might break strict clients, but user has test_bhavya
                pass

    result = db["roles"].insert_one(doc)
    
    # Manual Response Construction for Role
    response_data = {
        "id": str(result.inserted_id),
        "role": doc.get("role"),
        "description": doc.get("description"),
        "is_delete": doc.get("is_delete", False),
        "permission": [
            {
                "module_id": str(p.get("module_id", "")),
                "module_name": p.get("module_name"),
                "view": p.get("view", False),
                "add": p.get("add", False),
                "edit": p.get("edit", False),
                "delete": p.get("delete", False)
            }
            for p in doc.get("permission", [])
        ]
    }

    return {
        "data": {
            "status": 201,
            "message": "Role created successfully.",
            "role": response_data
        }
    }

@router.get("/roles")
async def get_all_roles():
    roles = []
    for r in db["roles"].find():
        role_data = {
            "id": str(r["_id"]),
            "role": r.get("role"),
            "is_delete": r.get("is_delete", False),
            "permission": [
                {
                    "module_id": str(p.get("module_id", "")),
                    "module_name": p.get("module_name"),
                    "view": p.get("view", False),
                    "add": p.get("add", False),
                    "edit": p.get("edit", False),
                    "delete": p.get("delete", False)
                }
                for p in r.get("permission", [])
            ]
        }
        roles.append(role_data)
    
    return {
        "data": {
            "status": 200,
            "message": "Roles retrieved successfully.",
            "roles": roles
        }
    }

@router.get("/roles/{id}")
async def get_role_by_id(id: str):
    r = db["roles"].find_one({"_id": ObjectId(id)})
    if not r:
        raise HTTPException(status_code=404, detail="Role not found")
    
    role_formatted = {
        "id": str(r["_id"]),
        "role": r.get("role"),
        "is_delete": r.get("is_delete", False),
        "permission": [
            {
                "module_id": str(p.get("module_id", "")),
                "module_name": p.get("module_name"),
                "view": p.get("view", False),
                "add": p.get("add", False),
                "edit": p.get("edit", False),
                "delete": p.get("delete", False)
            }
            for p in r.get("permission", [])
        ]
    }
    return {
        "data": {
            "status": 200,
            "message": "Role retrieved successfully.",
            "role": role_formatted
        }
    }

@router.put("/roles/{id}")
async def edit_role(id: str, data: RoleBase):
    doc = data.dict()
    
    # Auto-fetch module_id if missing (Same logic as Create)
    for p in doc["permission"]:
        if not p.get("module_id"):
            perm_doc = db["permissions"].find_one({"code": p["module_name"]})
            if perm_doc:
                p["module_id"] = str(perm_doc["_id"])

    db["roles"].update_one({"_id": ObjectId(id)}, {"$set": doc})
    r = db["roles"].find_one({"_id": ObjectId(id)})
    
    role_formatted = {
        "id": str(r["_id"]),
        "role": r.get("role"),
        "description": r.get("description"), # Return description
        "is_delete": r.get("is_delete", False),
        "permission": [
            {
                "module_id": str(p.get("module_id", "")),
                "module_name": p.get("module_name"),
                "view": p.get("view", False),
                "add": p.get("add", False),
                "edit": p.get("edit", False),
                "delete": p.get("delete", False)
            }
            for p in r.get("permission", [])
        ]
    }
    
    return {
        "data": {
            "status": 200,
            "message": "Role updated successfully.",
            "role": role_formatted
        }
    }

@router.delete("/roles/{id}")
async def delete_role(id: str):
    result = db["roles"].delete_one({"_id": ObjectId(id)})
    if result.deleted_count == 0:
        raise HTTPException(status_code=404, detail="Role not found")
    return {
        "data": {
            "status": 200,
            "message": "Role deleted successfully.",
            "result": None
        }
    }

#  Auth APIs 

@router.post("/login")
async def login(data: LoginRequest):
    admin = admins_collection.find_one({
        "$or": [
            {"email": data.email},
            {"username": data.email}
        ]
    })
    
    if not admin:
        return JSONResponse(
            status_code=404,
            content={
                "data": {
                    "status": 404,
                    "message": "account not found.",
                    "user": None
                }
            }
        )
    
    if not verify_password(data.password, admin["password"]):
        return JSONResponse(
            status_code=400,
            content={
                "data": {
                    "status": 400,
                    "message": "Invalid credentials.",
                    "user": None
                }
            }
        )
    
    role_info = None
    if admin.get("role_id"):
        role_doc = db["roles"].find_one({"_id": ObjectId(admin["role_id"])})
        if role_doc:
            role_info = {
                "id": str(role_doc["_id"]),
                "role": role_doc.get("role"),
                "is_delete": role_doc.get("is_delete", False),
                "permission": [
                    {
                        "module_id": str(p.get("module_id", "")),
                        "module_name": p.get("module_name"),
                        "view": p.get("view", False),
                        "add": p.get("add", False),
                        "edit": p.get("edit", False),
                        "delete": p.get("delete", False)
                    }
                    for p in role_doc.get("permission", [])
                ]
            }

    access_token = create_access_token(data={"sub": admin.get("email") or admin.get("username")})
    return {
        "data": {
            "status": 200,
            "message": "Login successful.",
            "access_token": access_token,
            "token_type": "bearer",
            "user": {
                "id": str(admin["_id"]),
                "email": admin.get("email"),
                "username": admin["username"],
                "full_name": admin.get("full_name"),
                "role": role_info
            }
        }
    }

@router.get("/user/{user_id}")
async def get_user(user_id: str):
    try:
        admin = admins_collection.find_one({"_id": ObjectId(user_id)})
        if not admin:
            raise HTTPException(status_code=404, detail="User not found")
        
        return {
            "data": {
                "status": 200,
                "message": "User details retrieved successfully.",
                "id": str(admin["_id"]),
                "email": admin.get("email"),
                "username": admin["username"],
            "full_name": admin.get("full_name"),
                "role_id": str(admin.get("role_id")) if admin.get("role_id") else None
            }
        }
    except Exception:
        raise HTTPException(status_code=400, detail="Invalid User ID format")

#  User Management APIs 

class AdminCreate(BaseModel):
    email: str
    username: str
    password: str
    full_name: str
    role_id: Optional[str] = None

class AdminUpdate(BaseModel):
    email: Optional[str] = None
    username: Optional[str] = None
    password: Optional[str] = None
    full_name: Optional[str] = None
    role_id: Optional[str] = None

@router.post("/users", status_code=201)
async def create_admin(data: AdminCreate):
    # Check if email/username already exists
    if admins_collection.find_one({"$or": [{"email": data.email}, {"username": data.username}]}):
        return JSONResponse(
            status_code=400,
            content={
                "data": {
                    "status": 400,
                    "message": "Email or Username already exists.",
                    "user": None
                }
            }
        )
    
    admin_doc = data.dict()
    admin_doc["password"] = get_password_hash(data.password)
    
    # Validate Role ID and fetching Role Name
    role_name = None
    if admin_doc.get("role_id"):
        try:
            role = db["roles"].find_one({"_id": ObjectId(admin_doc["role_id"])})
            if role:
                 role_name = role.get("role")
            else:
                 # If invalid role_id provided, reset it or raise error. 
                 # Here we clear it to avoid broken links
                 admin_doc["role_id"] = None
        except:
             admin_doc["role_id"] = None

    result = admins_collection.insert_one(admin_doc)
    
    return {
        "data": {
            "status": 201,
            "message": "Admin user created successfully.",
            "user": {
                "id": str(result.inserted_id),
                "email": admin_doc["email"],
                "username": admin_doc["username"],
                "full_name": admin_doc["full_name"],
                "role_id": admin_doc.get("role_id"),
                "role_name": role_name # Added field
            }
        }
    }

@router.get("/users")
async def get_all_admins():
    users = []
    # Pre-fetch all roles to avoid N+1 query problem
    try:
        roles_map = {str(r["_id"]): r.get("role", "Unknown") for r in db["roles"].find()}
    except:
        roles_map = {}

    for u in admins_collection.find():
        # Skip the restricted 'admin' user from the list
        if u.get("username") == "admin":
            continue

        r_id = u.get("role_id")
        r_name = roles_map.get(str(r_id)) if r_id and str(r_id) in roles_map else None

        users.append({
            "id": str(u["_id"]),
            "email": u.get("email"),
            "username": u.get("username"),
            "full_name": u.get("full_name"),
            "role_id": str(r_id) if r_id else None,
            "role_name": r_name # Include role Name
        })
    return {
        "data": {
            "status": 200,
            "message": "Admin users retrieved successfully.",
            "users": users
        }
    }

@router.put("/users/{id}")
async def update_admin(id: str, data: AdminUpdate):
    update_data = {k: v for k, v in data.dict().items() if v is not None}
    
    # Password hashing
    if "password" in update_data:
        update_data["password"] = get_password_hash(update_data["password"])
        
    # Validation for role_id
    if "role_id" in update_data and update_data["role_id"]:
        try:
             if not db["roles"].find_one({"_id": ObjectId(update_data["role_id"])}):
                 update_data["role_id"] = None
        except:
             update_data["role_id"] = None
    
    result = admins_collection.update_one({"_id": ObjectId(id)}, {"$set": update_data})
    if result.matched_count == 0:
         raise HTTPException(status_code=404, detail="User not found")

    u = admins_collection.find_one({"_id": ObjectId(id)})
    
    # Fetch Role Name for response
    role_name = None
    if u.get("role_id"):
        try:
             r = db["roles"].find_one({"_id": ObjectId(u["role_id"])})
             if r: role_name = r.get("role")
        except: pass

    return {
        "data": {
            "status": 200,
            "message": "Admin user updated successfully.",
            "user": {
                "id": str(u["_id"]),
                "email": u.get("email"),
                "username": u.get("username"),
                "full_name": u.get("full_name"),
                "role_id": str(u.get("role_id")) if u.get("role_id") else None,
                "role_name": role_name
            }
        }
    }

@router.delete("/users/{id}")
async def delete_admin(id: str):
    result = admins_collection.delete_one({"_id": ObjectId(id)})
    if result.deleted_count == 0:
        raise HTTPException(status_code=404, detail="User not found")
    return {
        "data": {
            "status": 200,
            "message": "Admin user deleted successfully.",
            "result": None
        }
    }

#  Dynamic Prompt APIs 
from src.utils.prompts import DEFAULT_SYSTEM_PROMPT

class PromptUpdate(BaseModel):
    content: Optional[str] = None
    prompt: Optional[str] = None
    is_active: bool = True

@router.get("/prompts")
async def list_all_prompts():
    """List all custom prompts stored in database."""
    prompts = []
    # Sort by ID (Creation Order) to keep the list stable in UI
    for p in db["prompts"].find().sort("_id", 1):
        prompts.append({
            "id": str(p["_id"]),
            "content": p.get("content"),
            "is_active": p.get("is_active", False),
            "updated_at": p.get("updated_at", datetime.utcnow())
        })
    
    return {
        "status": 200,
        "message": "Prompts retrieved successfully.",
        "data": {
            "prompts": prompts,
            "default_prompt": DEFAULT_SYSTEM_PROMPT
        }
    }

@router.get("/prompts/{id}")
async def get_prompt_by_id(id: str):
    """Get a specific prompt by ID."""
    prompt = db["prompts"].find_one({"_id": ObjectId(id)})
    if not prompt:
        raise HTTPException(status_code=404, detail="Prompt not found")
    
    return {
        "status": 200,
        "message": "Prompt retrieved successfully.",
        "data": {
            "id": str(prompt["_id"]),
            "content": prompt.get("content"),
            "is_active": prompt.get("is_active", False),
            "updated_at": prompt.get("updated_at")
        }
    }

@router.post("/prompts")
async def create_prompt(request: Request):
    """Create a new prompt."""
    try:
        data = await request.json()
        content = data.get("content") or data.get("prompt")
        is_active = data.get("is_active", True)

        if not content:
            return JSONResponse(status_code=400, content={"status": 400, "message": "Content is required", "data": None})

        # Logic: Multiple can be active now, AI picks most recent
        # if is_active:
        #     db["prompts"].update_many({}, {"$set": {"is_active": False}})

        doc = {
            "content": content,
            "is_active": is_active,
            "updated_at": datetime.utcnow()
        }
        result = db["prompts"].insert_one(doc)
        
        # Clear cache so AI picks up new prompt immediately
        service = get_assistant_service()
        if service:
            service.clear_cache()
        
        return {
            "status": 201,
            "message": "Prompt created successfully.",
            "data": {"id": str(result.inserted_id), "is_active": is_active}
        }
    except Exception as e:
        return JSONResponse(status_code=500, content={"status": 500, "message": str(e), "data": None})

@router.put("/prompts/{id}")
async def edit_prompt(id: str, request: Request):
    """Edit an existing prompt."""
    try:
        data = await request.json()
        content = data.get("content") or data.get("prompt")
        
        if not content:
            return JSONResponse(status_code=400, content={"status": 400, "message": "Content is required", "data": None})

        update_result = db["prompts"].update_one(
            {"_id": ObjectId(id)}, 
            {"$set": {"content": content, "updated_at": datetime.utcnow()}}
        )
        
        if update_result.matched_count == 0:
            raise HTTPException(status_code=404, detail="Prompt not found")

        # Clear cache so AI picks up updated prompt immediately
        service = get_assistant_service()
        if service:
            service.clear_cache()

        return {
            "status": 200,
            "message": "Prompt updated successfully.",
            "data": {"id": id}
        }
    except Exception as e:
        return JSONResponse(status_code=500, content={"status": 500, "message": str(e), "data": None})

@router.patch("/prompts/{id}/status")
async def update_prompt_status(id: str, request: Request):
    """Update active status of a prompt."""
    try:
        data = await request.json()
        is_active = data.get("is_active")
        
        if is_active is None:
            return JSONResponse(status_code=400, content={"status": 400, "message": "is_active field is required", "data": None})

        # Logic: Multiple can be active now, AI picks most recent
        # if is_active:
        #     db["prompts"].update_many({}, {"$set": {"is_active": False}})

        result = db["prompts"].update_one({"_id": ObjectId(id)}, {"$set": {"is_active": is_active, "updated_at": datetime.utcnow()}})
        
        if result.matched_count == 0:
            raise HTTPException(status_code=404, detail="Prompt not found")
        
        # Clear cache so AI picks up status change immediately
        service = get_assistant_service()
        if service:
            service.clear_cache()

        return {
            "status": 200, 
            "message": f"Prompt {'activated' if is_active else 'deactivated'} successfully.",
            "data": {"id": id, "is_active": is_active}
        }
    except Exception as e:
        return JSONResponse(status_code=500, content={"status": 500, "message": str(e), "data": None})

@router.delete("/prompts/{id}")
async def delete_prompt(id: str):
    """Delete a prompt."""
    result = db["prompts"].delete_one({"_id": ObjectId(id)})
    if result.deleted_count == 0:
        raise HTTPException(status_code=404, detail="Prompt not found")
    
    # Clear cache so AI picks up deletion immediately
    service = get_assistant_service()
    if service:
        service.clear_cache()

    return {
        "status": 200,
        "message": "Prompt deleted successfully.",
        "data": None
    }

#  File Management APIs 

#  Folder Management APIs (NEW)


class FolderCreate(BaseModel):
    folder_name: str

@router.post("/folders/create", status_code=201)
async def create_folder(data: FolderCreate):
    """Create a new folder"""
    existing = db["document_folders"].find_one({"folder_name": data.folder_name})
    if existing:
        return JSONResponse(
            status_code=400,
            content={
                "data": {
                    "status": 400,
                    "message": "Folder already exists",
                    "folder": None
                }
            }
        )
    
    folder_doc = {
        "folder_name": data.folder_name,
        "created_at": datetime.utcnow(),
        "updated_at": datetime.utcnow(),
        "file_count": 0
    }
    result = db["document_folders"].insert_one(folder_doc)
    
    folder_path = pathlib.Path(settings.DATA_DIR) / str(result.inserted_id)
    folder_path.mkdir(parents=True, exist_ok=True)
    
    return {
        "data": {
            "status": 201,
            "message": "Folder created successfully",
            "folder": {
                "folder_id": str(result.inserted_id),
                "folder_name": data.folder_name,
                "created_at": folder_doc["created_at"],
                "file_count": 0
            }
        }
    }

@router.post("/folders/upload-file")
async def upload_file_to_folder(
    request: Request,
    folder_name: str = Form(...),
    folder_id: Optional[str] = Form(None)
):
    """Upload multiple files to folder"""
    print(f"\n=== FOLDER UPLOAD REQUEST ===")
    print(f"folder_name: {folder_name}")
    print(f"folder_id: {folder_id}")
    
    form = await request.form()
    print(f"Form keys: {list(form.keys())}")
    
    files = form.getlist('files') or form.getlist('file')
    print(f"Files received: {len(files) if files else 0}")
    
    if files:
        for idx, f in enumerate(files):
            print(f"File {idx+1}: {f.filename if hasattr(f, 'filename') else 'NO FILENAME'}")
    
    if not files:
        print("ERROR: No files found in request")
        raise HTTPException(status_code=422, detail="No files provided. Use 'files' or 'file' field name")
    # 1. Determine folder_id (use existing or create new)
    final_folder_id = None
    final_folder_name = folder_name
    
    if folder_id:
        folder = db["document_folders"].find_one({"_id": ObjectId(folder_id)})
        if folder:
            final_folder_id = folder_id
            final_folder_name = folder["folder_name"]
        else:
            raise HTTPException(status_code=404, detail="Folder not found")
    else:
        folder = db["document_folders"].find_one({"folder_name": folder_name})
        if folder:
            final_folder_id = str(folder["_id"])
            final_folder_name = folder["folder_name"]
        else:
            new_folder = {
                "folder_name": folder_name,
                "created_at": datetime.utcnow(),
                "updated_at": datetime.utcnow(),
                "file_count": 0
            }
            result = db["document_folders"].insert_one(new_folder)
            final_folder_id = str(result.inserted_id)
    
    # 2. Create folder directory
    data_dir = pathlib.Path(settings.DATA_DIR) / final_folder_id
    data_dir.mkdir(parents=True, exist_ok=True)
    
    uploaded_files = []
    failed_files = []
    
    # 3. Process each file
    print(f"\nProcessing {len(files)} files...")
    for file in files:
        print(f"\n--- Processing: {file.filename} ---")
        if not file.filename.lower().endswith(".pdf"):
            print(f"REJECTED: Not a PDF file")
            failed_files.append({"filename": file.filename, "reason": "Only PDF files allowed"})
            continue
        
        file_path = data_dir / file.filename
        print(f"Saving to: {file_path}")
        
        try:
            with open(file_path, "wb") as buffer:
                shutil.copyfileobj(file.file, buffer)
            print(f"File saved successfully, size: {os.path.getsize(file_path)} bytes")
        except Exception as e:
            print(f"ERROR saving file: {e}")
            failed_files.append({"filename": file.filename, "reason": f"Save failed: {e}"})
            continue
        
        file_doc = {
            "filename": file.filename,
            "folder_id": ObjectId(final_folder_id),
            "folder_name": final_folder_name,
            "upload_date": datetime.utcnow(),
            "status": "Indexing",
            "size": os.path.getsize(file_path)
        }
        file_result = db["files"].insert_one(file_doc)
        print(f"DB record created: {file_result.inserted_id}")
        
        status_msg = "Indexed"
        try:
            service = get_assistant_service()
            if service:
                print(f"Indexing file...")
                service.manager.index_single_file(file_path, folder_name=final_folder_name)
                db["files"].update_one(
                    {"_id": file_result.inserted_id},
                    {"$set": {"status": "Indexed"}}
                )
                print(f"File indexed successfully")
        except Exception as e:
            print(f"ERROR indexing: {e}")
            status_msg = "Failed"
            db["files"].update_one(
                {"_id": file_result.inserted_id},
                {"$set": {"status": "Failed"}}
            )
        
        uploaded_files.append({
            "file_id": str(file_result.inserted_id),
            "filename": file.filename,
            "status": status_msg
        })
    
    # 4. Update folder file count
    db["document_folders"].update_one(
        {"_id": ObjectId(final_folder_id)},
        {
            "$inc": {"file_count": len(uploaded_files)},
            "$set": {"updated_at": datetime.utcnow()}
        }
    )
    
    print(f"\n=== UPLOAD COMPLETE ===")
    print(f"Uploaded: {len(uploaded_files)} files")
    print(f"Failed: {len(failed_files)} files")
    print(f"Folder ID: {final_folder_id}")
    print(f"========================\n")
    
    return {
        "data": {
            "status": 201,
            "message": f"{len(uploaded_files)} file(s) uploaded to folder",
            "folder_id": final_folder_id,
            "folder_name": final_folder_name,
            "uploaded_files": uploaded_files,
            "failed_files": failed_files
        }
    }
@router.get("/folders")
async def list_folders(page: int = 1, limit: int = 10):
    """Get all folders with file counts (Paginated)"""
    skip = (page - 1) * limit
    total_folders = db["document_folders"].count_documents({})
    
    folders = []
    for f in db["document_folders"].find().sort("created_at", -1).skip(skip).limit(limit):
        folders.append({
            "folder_id": str(f["_id"]),
            "folder_name": f["folder_name"],
            "created_at": f["created_at"],
            "updated_at": f["updated_at"],
            "file_count": f.get("file_count", 0)
        })
    
    return {
        "status": 200,
        "message": "Folders retrieved successfully",
        "data": {
            "folders": folders,
            "pagination": {
                "total": total_folders,
                "page": page,
                "limit": limit,
                "pages": (total_folders + limit - 1) // limit
            }
        }
    }

@router.get("/folders/{folder_id}/files")
async def get_folder_files(folder_id: str, page: int = 1, limit: int = 10):
    """Get all files in a specific folder with pagination"""
    # Get folder info
    folder = db["document_folders"].find_one({"_id": ObjectId(folder_id)})
    if not folder:
        raise HTTPException(status_code=404, detail="Folder not found")
    
    # Calculate pagination
    skip = (page - 1) * limit
    total_files = db["files"].count_documents({"folder_id": ObjectId(folder_id)})
    
    # Get files in folder
    files = []
    for f in db["files"].find({"folder_id": ObjectId(folder_id)}).sort("upload_date", -1).skip(skip).limit(limit):
        files.append({
            "file_id": str(f["_id"]),
            "filename": f["filename"],
            "upload_date": f["upload_date"],
            "status": f.get("status", "Unknown"),
            "size": f.get("size", 0)
        })
    
    return {
        "status": 200,
        "message": "Files retrieved successfully",
        "data": {
            "folder": {
                "folder_id": folder_id,
                "folder_name": folder["folder_name"],
                "created_at": folder["created_at"],
                "updated_at": folder["updated_at"],
                "file_count": folder.get("file_count", 0)
            },
            "files": files,
            "pagination": {
                "total": total_files,
                "page": page,
                "limit": limit,
                "pages": (total_files + limit - 1) // limit
            }
        }
    }

@router.delete("/folders/{folder_id}")
async def delete_folder(folder_id: str):
    """Delete a folder and all its files from disk, DB, and Vector index."""
    folder = db["document_folders"].find_one({"_id": ObjectId(folder_id)})
    if not folder:
        raise HTTPException(status_code=404, detail="Folder not found")
    
    folder_name = folder["folder_name"]
    
    # 1. Delete vectors from Atlas
    try:
        service = get_assistant_service()
        if service:
            service.manager.delete_folder_vectors(folder_name)
    except Exception as e:
        print(f"Warning: Failed to delete vectors for folder {folder_name}: {e}")

    # 2. Delete files from disk
    folder_path = pathlib.Path(settings.DATA_DIR) / folder_id
    if folder_path.exists():
        shutil.rmtree(folder_path)

    # 3. Delete file records from DB
    db["files"].delete_many({"folder_id": ObjectId(folder_id)})

    # 4. Delete folder record from DB
    db["document_folders"].delete_one({"_id": ObjectId(folder_id)})

    return {
        "status": 200,
        "message": f"Folder '{folder_name}' and all its contents deleted successfully.",
        "data": None
    }

#  File Management APIs 

@router.post("/files/upload")
async def upload_file(request: Request, files: List[UploadFile] = File(None)):
    # Debug: Check what's being received
    if not files or (len(files) == 1 and not files[0].filename):
        # Try to get form data manually
        form = await request.form()
        files = form.getlist('files') or form.getlist('file')
        if not files:
            raise HTTPException(status_code=422, detail="No files provided. Use 'files' field name in form-data")
    uploaded_files = []
    failed_files = []
    
    data_dir = pathlib.Path(settings.DATA_DIR)
    data_dir.mkdir(parents=True, exist_ok=True)
    
    for file in files:
        # 1. Validate PDF
        if not file.filename.lower().endswith(".pdf"):
            failed_files.append({"filename": file.filename, "reason": "Only PDF files allowed"})
            continue
        
        # 2. Save to Disk
        file_path = data_dir / file.filename
        try:
            with open(file_path, "wb") as buffer:
                shutil.copyfileobj(file.file, buffer)
        except Exception as e:
            failed_files.append({"filename": file.filename, "reason": f"Save failed: {e}"})
            continue
            
        # 3. Save Record to DB
        file_doc = {
            "filename": file.filename,
            "upload_date": datetime.utcnow(),
            "status": "Indexing",
            "size": os.path.getsize(file_path)
        }
        result = db["files"].insert_one(file_doc)
        
        # 4. Trigger Indexing
        status_msg = "Indexed"
        try:
            service = get_assistant_service()
            if service:
                service.manager.index_single_file(file_path, folder_name=None)
                db["files"].update_one({"_id": result.inserted_id}, {"$set": {"status": "Indexed"}})
        except Exception as e:
            status_msg = "Failed"
            db["files"].update_one({"_id": result.inserted_id}, {"$set": {"status": "Failed"}})
        
        uploaded_files.append({
            "id": str(result.inserted_id),
            "filename": file.filename,
            "status": status_msg
        })
    
    return {
        "data": {
            "status": 200,
            "message": "Files uploaded successfully.",
            "result": None
        }
    }

class FileDeleteRequest(BaseModel):
    file_ids: Union[str, List[str]]

@router.delete("/files/delete/{file_id}")
async def delete_files(file_id: str, data: FileDeleteRequest):
    """
    Unified File Deletion Endpoint (Single or Multiple)
    - Single: {"file_ids": "id1"}
    - Multiple: {"file_ids": ["id1", "id2", "id3"]}
    """
    print(f"\n--- DELETE REQUEST RECEIVED ---")
    print(f"Payload: {data.dict()}")
    
    # Convert to list if single string
    file_ids = [data.file_ids] if isinstance(data.file_ids, str) else data.file_ids
    
    deleted_count = 0
    deleted_files_details = []
    errors = []
     
    for file_id in file_ids:
        try:
            # 1. Fetch file record
            file_doc = db["files"].find_one({"_id": ObjectId(file_id)})
            if not file_doc:
                errors.append(f"File {file_id} not found")
                continue
            
            filename = file_doc["filename"]
            folder_id = file_doc.get("folder_id")
            folder_name = file_doc.get("folder_name")
            
            # 2. Delete vectors
            service = get_assistant_service()
            if service:
                service.manager.delete_file_vectors(filename)
            
            # 3. Delete from disk
            if folder_id:
                file_path = pathlib.Path(settings.DATA_DIR) / str(folder_id) / filename
            else:
                file_path = pathlib.Path(settings.DATA_DIR) / filename
            
            if file_path.exists():
                file_path.unlink()
            
            # 4. Delete DB record
            db["files"].delete_one({"_id": ObjectId(file_id)})
            
            # 5. Update folder count
            if folder_id:
                db["document_folders"].update_one(
                    {"_id": ObjectId(folder_id)},
                    {"$inc": {"file_count": -1}}
                )
            
            deleted_files_details.append({
                "file_id": str(file_id),
                "filename": filename,
                "folder_id": str(folder_id) if folder_id else None,
                "folder_name": folder_name
            })
            deleted_count += 1
            print(f"Deleted: {filename}")
            
        except Exception as e:
            errors.append(f"Error deleting file {file_id}: {str(e)}")

    print(f"Summary: {deleted_count} files deleted, {len(errors)} errors.")
    return {
        "status": 200,
        "message": f"Successfully deleted {deleted_count} files.",
        "data": {
            "deleted_count": deleted_count,
            "deleted_files": deleted_files_details,
            "errors": errors
        }
    }

@router.get("/files/{file_id}/view")
async def view_pdf(file_id: str):
    """View/Fetch PDF file content directly."""
    try:
        file_doc = db["files"].find_one({"_id": ObjectId(file_id)})
        if not file_doc:
            raise HTTPException(status_code=404, detail="File record not found in database")
        
        filename = file_doc["filename"]
        folder_id = file_doc.get("folder_id")
        
        # Construct path
        if folder_id:
            file_path = pathlib.Path(settings.DATA_DIR) / str(folder_id) / filename
        else:
            file_path = pathlib.Path(settings.DATA_DIR) / filename
            
        if not file_path.exists():
            raise HTTPException(status_code=404, detail=f"Physical file not found at {file_path}")
            
        return FileResponse(
            path=file_path,
            media_type="application/pdf",
            filename=filename
        )
    except Exception as e:
        if isinstance(e, HTTPException):
            raise e
        raise HTTPException(status_code=500, detail=str(e))
