from fastapi import APIRouter, status, HTTPException, Depends
from app.database import get_database
from app.dependencies.auth import require_admin
from app.repositories.agent_repository import (
    create_agent,
    get_agent_by_email,
    get_agent_by_id,
    list_agents,
    update_agent,
    count_active_admins,
    reset_agent_password
)
from app.models.auth import (
    CreateAgentRequest,
    UpdateAgentRequest,
    ResetAgentPasswordRequest,
    SafeAgentInfo
)

router = APIRouter(prefix="/api/v1/admin/agents", tags=["admin-agents"])

def format_safe_agent(agent_doc: dict) -> SafeAgentInfo:
    """Helper to convert MongoDB agent document into safe Pydantic model."""
    created_at = agent_doc.get("createdAt")
    updated_at = agent_doc.get("updatedAt")
    return SafeAgentInfo(
        agentId=agent_doc["agentId"],
        name=agent_doc.get("name", "Agent"),
        email=agent_doc["email"],
        role=agent_doc.get("role", "AGENT"),
        status=agent_doc.get("status", "ACTIVE"),
        createdAt=created_at.isoformat() if hasattr(created_at, "isoformat") else str(created_at) if created_at else None,
        updatedAt=updated_at.isoformat() if hasattr(updated_at, "isoformat") else str(updated_at) if updated_at else None
    )

@router.get("", response_model=list[SafeAgentInfo], status_code=status.HTTP_200_OK)
async def list_all_agents(current_admin: dict = Depends(require_admin)):
    """
    Lists all agents in MongoDB.
    Requires ADMIN authorization role.
    """
    db = get_database()
    agents = await list_agents(db)
    return [format_safe_agent(a) for a in agents]

@router.post("", response_model=SafeAgentInfo, status_code=status.HTTP_201_CREATED)
async def create_new_agent(
    payload: CreateAgentRequest,
    current_admin: dict = Depends(require_admin)
):
    """
    Creates a new agent with hashed password.
    Rejects duplicate email with HTTP 409 Conflict.
    Requires ADMIN authorization role.
    """
    db = get_database()
    normalized_email = payload.email.strip().lower()

    existing = await get_agent_by_email(db, normalized_email)
    if existing:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="Agent with this email already exists"
        )

    agent_doc = await create_agent(
        db,
        email=normalized_email,
        password=payload.password,
        name=payload.name,
        role=payload.role,
        status=payload.status
    )

    return format_safe_agent(agent_doc)

@router.get("/{agentId}", response_model=SafeAgentInfo, status_code=status.HTTP_200_OK)
async def get_agent_details(
    agentId: str,
    current_admin: dict = Depends(require_admin)
):
    """
    Returns single agent details by agentId.
    Requires ADMIN authorization role.
    """
    db = get_database()
    agent = await get_agent_by_id(db, agentId)
    if not agent:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Agent '{agentId}' not found"
        )
    return format_safe_agent(agent)

@router.patch("/{agentId}", response_model=SafeAgentInfo, status_code=status.HTTP_200_OK)
async def update_agent_details(
    agentId: str,
    payload: UpdateAgentRequest,
    current_admin: dict = Depends(require_admin)
):
    """
    Updates safe fields (name, role, status) for an agent.
    Enforces Last Active Admin protection.
    Requires ADMIN authorization role.
    """
    db = get_database()
    agent = await get_agent_by_id(db, agentId)
    if not agent:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Agent '{agentId}' not found"
        )

    updates = payload.model_dump(exclude_unset=True)

    # Last Active Admin Safety Check
    is_target_active_admin = (agent.get("role") == "ADMIN" and agent.get("status") == "ACTIVE")
    demoting_role = ("role" in updates and updates["role"] != "ADMIN")
    deactivating_status = ("status" in updates and updates["status"] != "ACTIVE")

    if is_target_active_admin and (demoting_role or deactivating_status):
        active_admins_count = await count_active_admins(db)
        if active_admins_count <= 1:
            raise HTTPException(
                status_code=status.HTTP_409_CONFLICT,
                detail="Cannot deactivate or demote the last active admin account"
            )

    updated_doc = await update_agent(db, agentId, updates)
    return format_safe_agent(updated_doc)

@router.post("/{agentId}/reset-password", response_model=SafeAgentInfo, status_code=status.HTTP_200_OK)
async def reset_agent_password_endpoint(
    agentId: str,
    payload: ResetAgentPasswordRequest,
    current_admin: dict = Depends(require_admin)
):
    """
    Resets an agent's password to a new bcrypt hash.
    Requires ADMIN authorization role.
    """
    db = get_database()
    agent = await get_agent_by_id(db, agentId)
    if not agent:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Agent '{agentId}' not found"
        )

    updated_doc = await reset_agent_password(db, agentId, payload.newPassword)
    return format_safe_agent(updated_doc)
