"""
User service routes for Memos-style backend.
"""

from typing import List

from fastapi import APIRouter, Body, Depends, HTTPException
from starlette.requests import Request

from common.encryption import mask_api_key, validate_openai_key_format
from common.memos_core.schemas import (
    UserCreate,
    UserUpdate,
    UserResponse,
)
from common.memos_core.services import get_user_service, get_user_settings_service


router = APIRouter(prefix="/users")


@router.get("", summary="List users", response_model=List[UserResponse])
async def list_users(user_service=Depends(get_user_service)):
    try:
        return await user_service.list_users()
    except Exception as exc:  # pragma: no cover
        raise HTTPException(status_code=500, detail=str(exc)) from exc


@router.post("", summary="Create user", response_model=UserResponse)
async def create_user(
    payload: dict = Body(default_factory=dict),
    user_service=Depends(get_user_service),
):
    try:
        # Accept both REST payload and Connect/proto-like envelope.
        # REST: { "email": "...", "password": "..." }
        # Possible envelope: { "user": { ... } } or other shapes.
        raw = payload.get("user") if isinstance(payload, dict) else None
        raw = raw if isinstance(raw, dict) else payload
        user_create = UserCreate(**(raw or {}))
        return await user_service.create_user(user_create)
    except Exception as exc:  # pragma: no cover
        raise HTTPException(status_code=400, detail=str(exc)) from exc


@router.post("/settings", summary="List user settings (Connect compatibility)")
async def list_user_settings_connect_compat(payload: dict = Body(default_factory=dict)):  # noqa: B008
    """
    Connect RPC UserService/ListUserSettings is proxied as:
      POST /api/v1/users/settings

    The real Memos API returns a ListUserSettingsResponse with `settings`, `next_page_token`, `total_size`.
    For stub backend, return empty list to let frontend proceed.
    """
    _ = payload
    return {
        "settings": [],
        "next_page_token": "",
        "total_size": 0,
    }


@router.get("/{user_id}", summary="Get user by ID", response_model=UserResponse)
async def get_user(user_id: str, user_service=Depends(get_user_service)):
    try:
        return await user_service.get_user(user_id)
    except Exception as exc:  # pragma: no cover
        raise HTTPException(status_code=404, detail=str(exc)) from exc


@router.patch("/{user_id}", summary="Update user", response_model=UserResponse)
async def update_user(
    user_id: str,
    payload: UserUpdate,
    user_service=Depends(get_user_service),
):
    try:
        return await user_service.update_user(user_id, payload)
    except Exception as exc:  # pragma: no cover
        raise HTTPException(status_code=400, detail=str(exc)) from exc


# =============================================================================
# OpenAI API Key Management Endpoints
# =============================================================================

@router.get("/{user_id}/openai-key", summary="Get user's OpenAI API key (masked)")
async def get_user_openai_key(
    user_id: str,
    request: Request,
    settings_service=Depends(get_user_settings_service),
):
    """
    Get user's OpenAI API key (masked for security).
    User can only access their own key.
    """
    # Verify user can only access their own key
    authenticated_user_id = getattr(request.state, "user_id", None)
    if not authenticated_user_id or authenticated_user_id != user_id:
        raise HTTPException(status_code=403, detail="You can only access your own API key")
    
    try:
        has_key = await settings_service.has_openai_api_key(user_id)
        if not has_key:
            return {"has_key": False, "masked_key": None}
        
        # Get the key to mask it
        key = await settings_service.get_openai_api_key(user_id)
        if key:
            return {
                "has_key": True,
                "masked_key": mask_api_key(key),
            }
        return {"has_key": False, "masked_key": None}
    except Exception as exc:
        raise HTTPException(status_code=500, detail=str(exc)) from exc


@router.put("/{user_id}/openai-key", summary="Update user's OpenAI API key")
async def update_user_openai_key(
    user_id: str,
    payload: dict = Body(...),
    request: Request,
    settings_service=Depends(get_user_settings_service),
):
    """
    Update user's OpenAI API key.
    Key will be encrypted before storage.
    User can only update their own key.
    """
    # Verify user can only update their own key
    authenticated_user_id = getattr(request.state, "user_id", None)
    if not authenticated_user_id or authenticated_user_id != user_id:
        raise HTTPException(status_code=403, detail="You can only update your own API key")
    
    api_key = payload.get("api_key") or payload.get("key")
    if not api_key:
        raise HTTPException(status_code=400, detail="api_key is required")
    
    # Validate key format
    if not validate_openai_key_format(api_key):
        raise HTTPException(
            status_code=400,
            detail="Invalid OpenAI API key format. Key must start with 'sk-' and be 20-100 characters."
        )
    
    try:
        await settings_service.set_openai_api_key(user_id, api_key)
        return {
            "success": True,
            "message": "OpenAI API key updated successfully",
            "masked_key": mask_api_key(api_key),
        }
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    except Exception as exc:
        raise HTTPException(status_code=500, detail=str(exc)) from exc


@router.delete("/{user_id}/openai-key", summary="Delete user's OpenAI API key")
async def delete_user_openai_key(
    user_id: str,
    request: Request,
    settings_service=Depends(get_user_settings_service),
):
    """
    Delete user's OpenAI API key.
    User can only delete their own key.
    """
    # Verify user can only delete their own key
    authenticated_user_id = getattr(request.state, "user_id", None)
    if not authenticated_user_id or authenticated_user_id != user_id:
        raise HTTPException(status_code=403, detail="You can only delete your own API key")
    
    try:
        await settings_service.delete_openai_api_key(user_id)
        return {"success": True, "message": "OpenAI API key deleted successfully"}
    except Exception as exc:
        raise HTTPException(status_code=500, detail=str(exc)) from exc


