"""Общие зависимости FastAPI: авторизация и сессия БД."""

import hashlib
from typing import Annotated, cast

from fastapi import Depends, HTTPException, Request
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.db import get_db
from app.models import McpToken

DbDep = Annotated[Session, Depends(get_db)]


def user_from_bearer(request: Request, db: Session) -> dict[str, str] | None:
    """Fallback-аутентификация API-клиентов без сессии (расширение, агенты):
    заголовок `Authorization: Bearer <MCP-токен>` → user_id владельца.

    Токен в БД хранится только как sha256-хэш (как в McpAuthMiddleware для /mcp).
    """
    auth = request.headers.get("authorization", "")
    token = auth.removeprefix("Bearer ").strip()
    if not token:
        return None
    token_hash = hashlib.sha256(token.encode()).hexdigest()
    user_id = db.scalar(select(McpToken.user_id).where(McpToken.token_hash == token_hash))
    if not user_id:
        return None
    # Минимальный пользователь: API/сервисы читают только user_id (ТЗ 1.2).
    return {"user_id": user_id}


def require_user(request: Request, db: DbDep) -> dict[str, str]:
    """Защита API: сессия SSO или Bearer MCP-токен (расширение, ИИ-агенты)."""
    user = request.session.get("user") or user_from_bearer(request, db)
    if not user:
        raise HTTPException(status_code=401, detail="Not authenticated")
    return cast(dict[str, str], user)


UserDep = Annotated[dict[str, str], Depends(require_user)]


def require_user_id(user: UserDep) -> str:
    """user_id текущего пользователя — ключ изоляции всех данных (ТЗ 1.2).

    Один слой чтения: require_user уже проверил 401.
    """
    return str(user["user_id"])


UserIdDep = Annotated[str, Depends(require_user_id)]
