"""JWT-Authentifizierung mit Magic-Link-Support und Multi-Tenancy."""
import secrets
from datetime import datetime, timedelta
from jose import jwt, JWTError
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from config import get_jwt_secret, JWT_ALGORITHM, JWT_EXPIRE_HOURS, TIMEZONE

security = HTTPBearer(auto_error=False)


JWT_ISSUER = "intelsight-osint"
JWT_AUDIENCE = "intelsight-osint"


def create_token(
    user_id: int,
    username: str,
    email: str,
    role: str = "member",
    tenant_id: int = None,
    org_slug: str = None,
    is_global_admin: bool = False,
) -> str:
    """JWT-Token erstellen mit Tenant-Kontext."""
    now = datetime.now(TIMEZONE)
    expire = now + timedelta(hours=JWT_EXPIRE_HOURS)
    payload = {
        "sub": str(user_id),
        "username": username,
        "email": email,
        "role": role,
        "tenant_id": tenant_id,
        "org_slug": org_slug,
        "is_global_admin": is_global_admin,
        "iss": JWT_ISSUER,
        "aud": JWT_AUDIENCE,
        "iat": now,
        "exp": expire,
    }
    return jwt.encode(payload, get_jwt_secret(), algorithm=JWT_ALGORITHM)


def decode_token(token: str) -> dict:
    """JWT-Token dekodieren und validieren."""
    try:
        payload = jwt.decode(
            token,
            get_jwt_secret(),
            algorithms=[JWT_ALGORITHM],
            issuer=JWT_ISSUER,
            audience=JWT_AUDIENCE,
        )
        return payload
    except JWTError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Token ungueltig oder abgelaufen",
        )


# --- Aktivitaets-Erfassung fuer MAU/DAU ---------------------------------------
# Je Nutzer und Kalendertag genau ein Eintrag in user_activity_days. Der
# In-Memory-Merker haelt die DB-Last bei einem INSERT je Nutzer und Tag.
# Ein Fehler hier darf NIEMALS eine Anfrage blockieren.
_activity_seen: set = set()


async def _track_activity(user_id: int, tenant_id) -> None:
    day = datetime.now(TIMEZONE).strftime("%Y-%m-%d")
    key = (user_id, day)
    if key in _activity_seen:
        return
    _activity_seen.add(key)
    if len(_activity_seen) > 20000:
        # Speicher begrenzen, alte Tage interessieren den Merker nicht mehr
        _activity_seen.clear()
        _activity_seen.add(key)
    try:
        import aiosqlite
        from config import DB_PATH
        db = await aiosqlite.connect(DB_PATH)
        try:
            await db.execute(
                "INSERT OR IGNORE INTO user_activity_days (user_id, day, tenant_id) VALUES (?, ?, ?)",
                (user_id, day, tenant_id),
            )
            await db.commit()
        finally:
            await db.close()
    except Exception:
        # Bewusst schlucken (z.B. Tabelle fehlt noch). Der Merker behaelt den
        # Schluessel, damit ein Dauerfehler nicht jede Anfrage erneut trifft.
        pass


async def get_current_user(
    credentials: HTTPAuthorizationCredentials = Depends(security),
) -> dict:
    """FastAPI Dependency: Aktuellen Nutzer aus Token extrahieren."""
    if credentials is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Nicht authentifiziert",
        )
    payload = decode_token(credentials.credentials)
    await _track_activity(int(payload["sub"]), payload.get("tenant_id"))
    return {
        "id": int(payload["sub"]),
        "username": payload["username"],
        "email": payload.get("email", ""),
        "role": payload.get("role", "member"),
        "tenant_id": payload.get("tenant_id"),
        "org_slug": payload.get("org_slug"),
        "is_global_admin": payload.get("is_global_admin", False),
    }


def generate_magic_token() -> str:
    """Generiert einen 64-Zeichen URL-safe Token."""
    return secrets.token_urlsafe(48)

