"""Inicjalizacja bazy DuckDB dla mcp_nostr_db.

Co robi (wszystko idempotent):
  1. Tworzy plik DB jeśli nie istnieje (a z `--clean` najpierw kasuje istniejący).
  2. Buduje schemę przez `IngestDaemonSQL._ensure_schema` — to samo wywołanie
     co w runtime'owym starcie, więc bootstrap jest gwarantowany identyczny.
  3. Wstawia listę `DEFAULT_RELAYS` jako aktywne relaye
     (`INSERT … ON CONFLICT DO NOTHING` — nie nadpisuje już istniejących).

Kiedy używać:
  - świeża instalacja albo nuke bazy (`rm nostr.duckdb` + uruchomienie tego),
  - użytkownik chce zalewane relaye po wyczyszczeniu rejestru.

Czego NIE robi:
  - nie startuje WebSocketów ani auto-trackera (to robi mcp_admin),
  - nie modyfikuje istniejących relayów (status / active),
  - nie kasuje danych eventów / pubkeyów / profile (one zostają).

Użycie:
    python init_db.py                  # init/seed pod NOSTR_DUCKDB_PATH (lub default)
    python init_db.py --clean          # kasuje plik DB i robi od zera
    python init_db.py /path/to/db      # explicit ścieżka
"""

from __future__ import annotations

import argparse
import logging
import os
from pathlib import Path

from ingest_sql import IngestDaemonSQL


# Lista wybrana z empirycznego rankingu produktywności (events_seen) tego
# deploymentu, z pominięciem premium-only / niestabilnych. Wszystkie publiczne,
# bez konta. Aktualizować gdy rynek relayów się zmienia — to NIE jest zamknięty
# kontrakt, raczej rozsądny start dla świeżej instalacji.
DEFAULT_RELAYS: tuple[str, ...] = (
    "wss://nos.lol",
    "wss://relay.damus.io",
    "wss://nostr.oxtr.dev",
    "wss://nostr.mom",
    "wss://nostr-01.yakihonne.com",
    "wss://relay.ditto.pub",
)


def _resolve_default_db_path() -> str:
    """Zachowanie zgodne z `mcp_admin.py`: env var nadpisuje default
    `mcp_nostr_db/duckdb/nostr.duckdb` (relatywnie od pliku skryptu)."""
    env = os.environ.get("NOSTR_DUCKDB_PATH")
    if env:
        return env
    return str(Path(__file__).parent.parent.parent / "duckdb" / "nostr.duckdb")


def init_db(db_path: str, *, clean: bool = False) -> dict:
    """Inicjalizuje bazę i zwraca podsumowanie. Bez efektów ubocznych poza
    plikiem DB pod `db_path`."""
    log = logging.getLogger("init_db")

    if clean and os.path.exists(db_path):
        # Razem z WAL / temp file (DuckDB potrafi zostawić *.wal / *.tmp).
        for suffix in ("", ".wal", ".tmp"):
            p = db_path + suffix
            if os.path.exists(p):
                os.unlink(p)
                log.info("removed %s", p)

    fresh = not os.path.exists(db_path)

    # IngestDaemonSQL.__init__ otwiera connection i woła _ensure_schema —
    # sam fakt skonstruowania obiektu wystarcza do bootstrapu.
    daemon = IngestDaemonSQL(db_path)

    inserted = 0
    skipped = 0
    try:
        with daemon._sql_lock:
            for url in DEFAULT_RELAYS:
                row = daemon._conn.execute(
                    "SELECT 1 FROM relays WHERE url = ?", [url],
                ).fetchone()
                if row is not None:
                    skipped += 1
                    continue
                daemon._conn.execute(
                    "INSERT INTO relays (url, active) VALUES (?, true)",
                    [url],
                )
                inserted += 1
    finally:
        # IngestDaemonSQL nie ma osobnego close — zamykamy connection
        # bezpośrednio. Nie startowaliśmy auto-trackera ani live_subs,
        # więc nie ma threadów do zatrzymania.
        try:
            daemon._conn.close()
        except Exception:
            pass

    return {
        "db_path": db_path,
        "fresh_file": fresh,
        "relays_inserted": inserted,
        "relays_skipped": skipped,
        "default_relays_total": len(DEFAULT_RELAYS),
    }


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__.split("\n")[0])
    parser.add_argument(
        "db_path",
        nargs="?",
        default=None,
        help="Ścieżka do pliku DuckDB (default: NOSTR_DUCKDB_PATH lub plik repo).",
    )
    parser.add_argument(
        "--clean",
        action="store_true",
        help="Usuń istniejący plik DB (i WAL) przed inicjalizacją.",
    )
    args = parser.parse_args()

    logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)s %(levelname)s %(message)s")
    log = logging.getLogger("init_db")

    db_path = args.db_path or _resolve_default_db_path()
    summary = init_db(db_path, clean=args.clean)
    log.info(
        "init_db: %s — fresh=%s, relays inserted=%d / skipped=%d (total seed=%d)",
        summary["db_path"],
        summary["fresh_file"],
        summary["relays_inserted"],
        summary["relays_skipped"],
        summary["default_relays_total"],
    )


if __name__ == "__main__":
    main()
