"""Directory bot registry: submitted groups/channels with super-user approval.

Mirrors the core of SimpleX's directory service: groups are registered (pending),
a super-user approves/rejects, and approved entries are published to the bot's
website (web/<safe>/data/listing.json) in the format index.html expects.

State is a per-bot JSON file so it survives restarts: data/bots/<safe>_directory.json
"""

import json
from datetime import datetime, timezone
from pathlib import Path

BASE = Path(__file__).parent
DATA_DIR = BASE / "data" / "bots"
WEB_DIR = BASE.parent / "web"


def _now() -> str:
    return datetime.now(timezone.utc).isoformat()


def _state_path(safe: str) -> Path:
    return DATA_DIR / f"{safe}_directory.json"


def load_state(safe: str) -> dict:
    p = _state_path(safe)
    if p.exists():
        try:
            return json.loads(p.read_text(encoding="utf-8"))
        except Exception:
            pass
    return {"seq": 0, "entries": []}


def save_state(safe: str, state: dict) -> None:
    DATA_DIR.mkdir(parents=True, exist_ok=True)
    _state_path(safe).write_text(json.dumps(state, indent=2), encoding="utf-8")


def find_by_group(state: dict, group_id: int) -> dict | None:
    for e in state["entries"]:
        if e["group_id"] == group_id:
            return e
    return None


def add_pending(
    safe: str, group_id: int, display_name: str, link: str,
    is_channel: bool, summary: dict, short_descr: str | None, submitted_by: str,
) -> tuple[dict, bool]:
    """Register a group as pending. Returns (entry, is_new)."""
    state = load_state(safe)
    existing = find_by_group(state, group_id)
    if existing:
        return existing, False
    state["seq"] += 1
    entry = {
        "id": state["seq"], "group_id": group_id, "status": "pending",
        "displayName": display_name, "link": link, "is_channel": bool(is_channel),
        "summary": summary or {}, "shortDescr": short_descr,
        "submitted_by": submitted_by, "createdAt": _now(), "activeAt": _now(),
    }
    state["entries"].append(entry)
    save_state(safe, state)
    return entry, True


def set_status(safe: str, entry_id: int, status: str) -> dict | None:
    state = load_state(safe)
    for e in state["entries"]:
        if e["id"] == entry_id:
            e["status"] = status
            save_state(safe, state)
            return e
    return None


def entries_by_status(safe: str, status: str) -> list[dict]:
    return [e for e in load_state(safe)["entries"] if e["status"] == status]


def search(safe: str, query: str) -> list[dict]:
    q = query.lower().strip()
    out = []
    for e in entries_by_status(safe, "approved"):
        if q in e["displayName"].lower() or (e.get("shortDescr") or "").lower().find(q) >= 0:
            out.append(e)
    return out


def publish(safe: str) -> int:
    """Write approved entries to web/<safe>/data/listing.json (website schema). Returns count."""
    entries = []
    for e in entries_by_status(safe, "approved"):
        entry_type = {
            "type": "channel" if e["is_channel"] else "group",
            "summary": e.get("summary") or {},
        }
        if e["is_channel"]:
            entry_type["groupType"] = "channel"
        entries.append({
            "entryType": entry_type,
            "displayName": e["displayName"],
            "groupLink": {"connShortLink": e["link"]} if e.get("link") else {},
            "shortDescr": e.get("shortDescr"),
            "createdAt": e["createdAt"],
            "activeAt": e["activeAt"],
        })
    out = WEB_DIR / safe / "data" / "listing.json"
    out.parent.mkdir(parents=True, exist_ok=True)
    out.write_text(json.dumps({"entries": entries}, indent=2), encoding="utf-8")
    return len(entries)
