"""Audit trail utilities for NEUROVAULT v0.3."""

from __future__ import annotations

import json
import time
from pathlib import Path
from typing import Any


class AuditTrail:
    """Append-only audit log with file-backed and storage-backed modes."""

    def __init__(self, log_path: str | Path | None = None, storage=None):
        self._storage = storage
        self._path = Path(log_path) if log_path else None
        if self._path is not None and self._storage is None:
            self._path.parent.mkdir(parents=True, exist_ok=True)

    def log(
        self,
        user: str,
        action: str,
        resource: str,
        details: dict[str, Any] | None = None,
        success: bool = True,
    ) -> None:
        entry = {
            "timestamp": int(time.time() * 1000),
            "user": user,
            "action": action,
            "resource": resource,
            "success": bool(success),
            "details": details or {},
        }

        if self._storage is not None:
            self._storage.insert_audit_log(
                {
                    "timestamp": entry["timestamp"],
                    "username": entry["user"],
                    "action": entry["action"],
                    "resource": entry["resource"],
                    "success": entry["success"],
                    "details": entry["details"],
                }
            )
            return

        if self._path is None:
            return
        with open(self._path, "a", encoding="utf-8") as handle:
            handle.write(json.dumps(entry) + "\n")

    def query(
        self,
        user: str | None = None,
        action: str | None = None,
        since: int | None = None,
        limit: int = 100,
    ) -> list[dict[str, Any]]:
        if self._storage is not None:
            return self._storage.query_audit_log(user=user, action=action, since=since, limit=limit)

        if self._path is None or not self._path.exists():
            return []

        rows: list[dict[str, Any]] = []
        with open(self._path, encoding="utf-8") as handle:
            for line in handle:
                line = line.strip()
                if not line:
                    continue
                try:
                    entry = json.loads(line)
                except Exception:
                    continue
                if not isinstance(entry, dict):
                    continue
                if user and entry.get("user") != user:
                    continue
                if action and entry.get("action") != action:
                    continue
                if since and int(entry.get("timestamp", 0)) < int(since):
                    continue
                rows.append(entry)

        return rows[-max(1, min(limit, 5000)) :]
