"""
Seed the BizNode bot knowledge base (biznode_memory Qdrant collection)
from the dashboard instruction.md / business profile.

Run from the node root:
    python scripts/seed_bot_kb.py

This populates Qdrant so the RAG pipeline can answer business-specific
questions instead of hallucinating.
"""

import os, sys, json, hashlib, struct, requests

# Load .env
_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
_env_path = os.path.join(_root, ".env")
if os.path.exists(_env_path):
    with open(_env_path, encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if "=" in line and not line.startswith("#"):
                k, v = line.split("=", 1)
                os.environ.setdefault(k.strip(), v.strip())

# Always use localhost — this script runs directly on the host, not inside Docker
DASHBOARD_URL    = "http://localhost:7777"
OLLAMA_EMBED_URL = os.getenv("OLLAMA_EMBED_URL", "http://localhost:11434/api/embeddings")
EMBED_MODEL      = os.getenv("EMBEDDING_MODEL", "nomic-embed-text")
QDRANT_URL       = os.getenv("QDRANT_URL", "http://localhost:6333")
COLLECTION       = "biznode_memory"
BOT_SECRET       = os.getenv("BOT_SECRET", "")
HEADERS          = {"X-Bot-Secret": BOT_SECRET} if BOT_SECRET else {}


def embed(text: str):
    r = requests.post(OLLAMA_EMBED_URL, json={"model": EMBED_MODEL, "prompt": text}, timeout=60)
    r.raise_for_status()
    return r.json().get("embedding")


def point_id(text: str) -> int:
    h = hashlib.sha256(f"seed:{text}".encode()).digest()
    return struct.unpack(">Q", h[:8])[0]


def upsert(title: str, content: str):
    print(f"  Embedding: {title[:60]}...")
    vector = embed(content[:1500])
    if not vector:
        print(f"    [SKIP] no embedding returned")
        return
    requests.put(
        f"{QDRANT_URL}/collections/{COLLECTION}/points",
        json={"points": [{"id": point_id(title), "vector": vector,
                           "payload": {"title": title, "content": content}}]},
        timeout=10,
    ).raise_for_status()
    print(f"    [OK]")


# ── 1. Pull business instruction from dashboard ───────────────────────────────
print("Fetching business instructions from dashboard...")
try:
    r = requests.get(f"{DASHBOARD_URL}/api/instruction", headers=HEADERS, timeout=5)
    instruction = r.json().get("content", "") if r.ok else ""
except Exception as e:
    instruction = ""
    print(f"  Warning: could not fetch instruction — {e}")

# ── 2. Pull business profile ──────────────────────────────────────────────────
print("Fetching business profile...")
try:
    r = requests.get(f"{DASHBOARD_URL}/api/business-profile", headers=HEADERS, timeout=5)
    profile = r.json() if r.ok else {}
except Exception:
    profile = {}

biz_name    = profile.get("business_name") or "1BZ DZIT DAO LLC"
persona     = profile.get("ai_persona_name") or "Priya"
description = profile.get("business_description") or ""
services    = profile.get("services_offered") or ""

# ── 3. Pull notes from dashboard (knowledge base articles) ───────────────────
print("Fetching knowledge base notes...")
try:
    r = requests.get(f"{DASHBOARD_URL}/api/notes", headers=HEADERS, timeout=5)
    notes = r.json() if r.ok and isinstance(r.json(), list) else []
except Exception:
    notes = []

# ── 4. Build articles to seed ─────────────────────────────────────────────────

articles = []

# Business overview
if description or biz_name:
    articles.append({
        "title": f"About {biz_name}",
        "content": f"{biz_name}\n\n{description or ''}\n\nServices: {services or ''}".strip(),
    })

# Full instruction (split into sections)
if instruction:
    articles.append({
        "title": "Business AI Instructions — Full",
        "content": instruction[:3000],
    })
    if len(instruction) > 3000:
        articles.append({
            "title": "Business AI Instructions — Continued",
            "content": instruction[3000:6000],
        })

# KB notes
for note in notes:
    title   = (note.get("title") or "Note").strip()
    content = (note.get("content") or "").strip()
    if content:
        articles.append({"title": title, "content": content})

# BizNode system-specific articles
articles += [
    {
        "title": "How BizNode stores memory",
        "content": (
            "BizNode stores memory using a dual-layer system:\n\n"
            "1. Qdrant (vector database): Every customer message and knowledge base article "
            "is embedded using a local Ollama embedding model (nomic-embed-text) and stored "
            "as a vector in a Qdrant collection called 'biznode_memory'. This allows semantic "
            "search — finding relevant information even if the exact words don't match.\n\n"
            "2. SQLite or PostgreSQL (structured database): Leads, conversations, tasks, "
            "workflow state, customer profiles, and all business data are stored in a relational "
            "database. The database is accessed via memory/database.py.\n\n"
            "When a customer asks a question, BizNode embeds the question, searches Qdrant for "
            "the most relevant stored knowledge, and passes that context to the local Ollama LLM "
            "to generate an accurate answer. This is called RAG (Retrieval-Augmented Generation)."
        ),
    },
    {
        "title": "What is BizNode",
        "content": (
            "BizNode is a portable, autonomous AI business node that runs on your own hardware. "
            "It combines a Telegram AI assistant, a business dashboard, a RAG knowledge base, "
            "and workflow automation — all self-hosted with local Ollama LLM and Qdrant vector DB.\n\n"
            "BizNode enables businesses to:\n"
            "- Run their own private AI assistant on Telegram\n"
            "- Store and query a local business knowledge base\n"
            "- Automate lead capture and customer onboarding\n"
            "- Execute scheduled tasks and email workflows\n"
            "- Operate without depending on cloud AI providers\n\n"
            f"This instance is operated by {biz_name}, with AI assistant named {persona}."
        ),
    },
    {
        "title": "BizNode technical architecture",
        "content": (
            "BizNode technical stack:\n\n"
            "- Telegram Bot (python-telegram-bot): Customer-facing AI assistant\n"
            "- FastAPI Dashboard (port 7777): Owner control panel with REST API\n"
            "- Ollama (port 11434): Local LLM inference — no cloud dependency\n"
            "- Qdrant (port 6333): Vector database for RAG knowledge retrieval\n"
            "- SQLite / PostgreSQL: Structured data — leads, workflows, tasks\n"
            "- APScheduler: Cron-based task automation\n"
            "- IMAP email inbox: Owner sends instructions by email, bot executes them\n\n"
            "The bot uses a state machine for customer onboarding: "
            "new → name → business → email → OTP verification → verified.\n"
            "After verification, customers interact with workflows and the knowledge base."
        ),
    },
    {
        "title": "BizNode services and pricing",
        "content": (
            f"{biz_name} provides AI automation consulting and implementation services.\n\n"
            "Services include:\n"
            "- AI Automation Consulting: Design and implement AI systems for business operations\n"
            "- Autonomous Business Agents: Custom AI agents for communication and workflows\n"
            "- Telegram AI Bots: Intelligent bots for customer interaction\n"
            "- Business Infrastructure: Scalable technology stacks\n"
            "- Workflow Automation: Eliminate repetitive processes with AI\n"
            "- Decentralized AI Infrastructure: Deploy portable AI nodes like BizNode\n\n"
            "To get started, share your business type, what you want to automate, "
            "and your current technology setup. We'll guide you through the next steps."
        ),
    },
]

# ── 5. Ensure collection exists ───────────────────────────────────────────────
print(f"\nEnsuring Qdrant collection '{COLLECTION}' exists...")
try:
    r = requests.get(f"{QDRANT_URL}/collections/{COLLECTION}", timeout=5)
    if r.status_code == 404:
        # Get embedding dimension
        test_vec = embed("test")
        dim = len(test_vec) if test_vec else 768
        requests.put(
            f"{QDRANT_URL}/collections/{COLLECTION}",
            json={"vectors": {"size": dim, "distance": "Cosine"}},
            timeout=10,
        ).raise_for_status()
        print(f"  Created collection with dim={dim}")
    else:
        print(f"  Collection exists")
except Exception as e:
    print(f"  Error: {e}")
    sys.exit(1)

# ── 6. Seed articles ──────────────────────────────────────────────────────────
print(f"\nSeeding {len(articles)} articles into '{COLLECTION}'...")
ok = 0
for article in articles:
    try:
        upsert(article["title"], article["content"])
        ok += 1
    except Exception as e:
        print(f"  [ERROR] {article['title']}: {e}")

# ── 7. Done ───────────────────────────────────────────────────────────────────
try:
    r = requests.get(f"{QDRANT_URL}/collections/{COLLECTION}", timeout=5)
    total = r.json().get("result", {}).get("points_count", "?")
except Exception:
    total = "?"

print(f"\nDone. {ok}/{len(articles)} articles seeded. Collection now has {total} total points.")
