"""
Moderation — Block, unblock, and report users.

Blocked users are stored locally at ``~/.brynq/blocked.json``.
Reports are sent to the cloud API (``POST /v1/abuse/report``).
"""

from __future__ import annotations

import json
import logging
import time
import threading
from pathlib import Path
from typing import Optional

logger = logging.getLogger("brynq.security.moderation")

BLOCKED_FILE = Path.home() / ".brynq" / "blocked.json"


class ModerationManager:
    """Local block list + cloud abuse reporting."""

    def __init__(self, path: Path | str | None = None):
        self._path = Path(path) if path else BLOCKED_FILE
        self._lock = threading.Lock()
        self._blocked: dict[str, dict] = {}  # user_id -> {reason, blocked_at}
        self._load()

    # ── block / unblock ───────────────────────────────────────────────

    def block_user(self, user_id: str, reason: str = "") -> None:
        """Add *user_id* to the local block list."""
        with self._lock:
            self._blocked[user_id] = {
                "reason": reason,
                "blocked_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
            }
            self._save()
        logger.info("Blocked user %s: %s", user_id, reason or "(no reason)")

    def unblock_user(self, user_id: str) -> None:
        """Remove *user_id* from the local block list."""
        with self._lock:
            removed = self._blocked.pop(user_id, None)
            if removed:
                self._save()
                logger.info("Unblocked user %s", user_id)
            else:
                logger.info("User %s was not blocked", user_id)

    def is_blocked(self, user_id: str) -> bool:
        """Return whether *user_id* is currently blocked."""
        with self._lock:
            return user_id in self._blocked

    def list_blocked(self) -> dict[str, dict]:
        """Return a copy of the full block list."""
        with self._lock:
            return dict(self._blocked)

    # ── reporting ─────────────────────────────────────────────────────

    def report_user(
        self,
        user_id: str,
        reason: str,
        reporter_id: str = "",
        cloud_url: str = "",
    ) -> dict:
        """Send an abuse report to the cloud API.

        Returns the API response dict on success, or an error dict on failure.
        If no cloud URL is configured, the report is saved locally only.
        """
        report = {
            "reported_user_id": user_id,
            "reporter_id": reporter_id,
            "reason": reason,
            "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
        }

        # Always log locally
        self._append_local_report(report)

        if not cloud_url:
            logger.info("No cloud URL — report saved locally only")
            return {"status": "local_only", "report": report}

        # Send to cloud
        try:
            import urllib.request

            req = urllib.request.Request(
                f"{cloud_url}/v1/abuse/report",
                data=json.dumps(report).encode("utf-8"),
                headers={"Content-Type": "application/json"},
                method="POST",
            )
            with urllib.request.urlopen(req, timeout=10) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except Exception as exc:
            logger.error("Failed to send abuse report: %s", exc)
            return {"status": "error", "error": str(exc), "report": report}

    # ── persistence ───────────────────────────────────────────────────

    def _load(self) -> None:
        if self._path.exists():
            try:
                data = json.loads(self._path.read_text("utf-8"))
                self._blocked = data.get("blocked", {})
            except (json.JSONDecodeError, OSError) as exc:
                logger.warning("Failed to load block list: %s", exc)
                self._blocked = {}

    def _save(self) -> None:
        self._path.parent.mkdir(parents=True, exist_ok=True)
        self._path.write_text(
            json.dumps({"blocked": self._blocked}, indent=2),
            encoding="utf-8",
        )

    def _append_local_report(self, report: dict) -> None:
        """Append a report to the local security log."""
        log_path = self._path.parent / "security_log.jsonl"
        log_path.parent.mkdir(parents=True, exist_ok=True)
        with open(log_path, "a", encoding="utf-8") as f:
            f.write(json.dumps({"event": "abuse_report", **report}) + "\n")
