#!/usr/bin/env python3
"""
Local Honcho-compatible memory server for Hermes Agent.
Runs on localhost:8000, stores observations in SQLite.
"""

import asyncio
import json
import sqlite3
import uuid
from datetime import datetime
from pathlib import Path

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

DB_PATH = Path("/DATA/AppData/hermes/.honcho/local.db")
DB_PATH.parent.mkdir(parents=True, exist_ok=True)

app = FastAPI(title="Honcho Local", version="1.0.0")

# ── DB init ──
def init_db():
    conn = sqlite3.connect(str(DB_PATH))
    conn.executescript("""
        CREATE TABLE IF NOT EXISTS workspaces (
            id TEXT PRIMARY KEY,
            created_at TEXT
        );
        CREATE TABLE IF NOT EXISTS peers (
            id TEXT PRIMARY KEY,
            workspace_id TEXT,
            name TEXT,
            created_at TEXT
        );
        CREATE TABLE IF NOT EXISTS sessions (
            id TEXT PRIMARY KEY,
            workspace_id TEXT,
            created_at TEXT,
            metadata TEXT
        );
        CREATE TABLE IF NOT EXISTS messages (
            id TEXT PRIMARY KEY,
            session_id TEXT,
            peer_id TEXT,
            content TEXT,
            created_at TEXT,
            is_user INTEGER
        );
        CREATE TABLE IF NOT EXISTS observations (
            id TEXT PRIMARY KEY,
            session_id TEXT,
            peer_id TEXT,
            content TEXT,
            created_at TEXT
        );
    """)
    now = datetime.utcnow().isoformat()
    conn.execute("INSERT OR IGNORE INTO workspaces (id, created_at) VALUES (?, ?);", ("default", now))
    conn.commit()
    conn.close()

init_db()

def db():
    conn = sqlite3.connect(str(DB_PATH))
    conn.row_factory = sqlite3.Row
    return conn

# ── Models ──
class MessageIn(BaseModel):
    peer_id: str
    content: str
    is_user: bool = False

class ObservationIn(BaseModel):
    peer_id: str
    content: str

class ConfigIn(BaseModel):
    key: str
    value: str

# ── Routes ──

@app.get("/")
def root():
    return {"status": "ok", "service": "honcho-local"}

@app.get("/health")
def health():
    return {"status": "ok"}

# Workspaces
@app.get("/workspaces")
def list_workspaces():
    conn = db()
    rows = conn.execute("SELECT * FROM workspaces").fetchall()
    conn.close()
    return {"items": [dict(r) for r in rows]}

@app.post("/workspaces")
def create_workspace():
    wid = str(uuid.uuid4())
    conn = db()
    conn.execute("INSERT INTO workspaces (id, created_at) VALUES (?, ?)",
                 (wid, datetime.utcnow().isoformat()))
    conn.commit()
    conn.close()
    return {"id": wid}

# Peers
@app.get("/workspaces/{ws}/peers")
def list_peers(ws: str):
    conn = db()
    rows = conn.execute("SELECT * FROM peers WHERE workspace_id=?", (ws,)).fetchall()
    conn.close()
    return {"items": [dict(r) for r in rows]}

@app.post("/workspaces/{ws}/peers")
def create_peer(ws: str, name: str = "hermes"):
    pid = str(uuid.uuid4())
    conn = db()
    conn.execute("INSERT INTO peers (id, workspace_id, name, created_at) VALUES (?, ?, ?, ?)",
                 (pid, ws, name, datetime.utcnow().isoformat()))
    conn.commit()
    conn.close()
    return {"id": pid, "name": name}

# Sessions
@app.get("/workspaces/{ws}/sessions")
def list_sessions(ws: str):
    conn = db()
    rows = conn.execute("SELECT * FROM sessions WHERE workspace_id=?", (ws,)).fetchall()
    conn.close()
    return {"items": [dict(r) for r in rows]}

@app.post("/workspaces/{ws}/sessions")
def create_session(ws: str, metadata: str = "{}"):
    sid = str(uuid.uuid4())
    conn = db()
    conn.execute("INSERT INTO sessions (id, workspace_id, created_at, metadata) VALUES (?, ?, ?, ?)",
                 (sid, ws, datetime.utcnow().isoformat(), metadata))
    conn.commit()
    conn.close()
    return {"id": sid}

# Messages
@app.post("/workspaces/{ws}/sessions/{sid}/messages")
def add_message(ws: str, sid: str, msg: MessageIn):
    mid = str(uuid.uuid4())
    conn = db()
    conn.execute(
        "INSERT INTO messages (id, session_id, peer_id, content, created_at, is_user) VALUES (?, ?, ?, ?, ?, ?)",
        (mid, sid, msg.peer_id, msg.content, datetime.utcnow().isoformat(), 1 if msg.is_user else 0)
    )
    conn.commit()
    conn.close()
    return {"id": mid}

@app.get("/workspaces/{ws}/sessions/{sid}/messages")
def get_messages(ws: str, sid: str):
    conn = db()
    rows = conn.execute("SELECT * FROM messages WHERE session_id=? ORDER BY created_at", (sid,)).fetchall()
    conn.close()
    return {"items": [dict(r) for r in rows]}

# Observations
@app.post("/workspaces/{ws}/sessions/{sid}/observations")
def add_observation(ws: str, sid: str, obs: ObservationIn):
    oid = str(uuid.uuid4())
    conn = db()
    conn.execute(
        "INSERT INTO observations (id, session_id, peer_id, content, created_at) VALUES (?, ?, ?, ?, ?)",
        (oid, sid, obs.peer_id, obs.content, datetime.utcnow().isoformat())
    )
    conn.commit()
    conn.close()
    return {"id": oid}

@app.get("/workspaces/{ws}/sessions/{sid}/observations")
def get_observations(ws: str, sid: str):
    conn = db()
    rows = conn.execute("SELECT * FROM observations WHERE session_id=? ORDER BY created_at DESC", (sid,)).fetchall()
    conn.close()
    return {"items": [dict(r) for r in rows]}

# Configuration / metadata
@app.get("/workspaces/{ws}/config")
def get_config(ws: str):
    return {"key": "default", "value": "{}"}

@app.post("/workspaces/{ws}/config")
def set_config(ws: str, cfg: ConfigIn):
    return {"key": cfg.key, "value": cfg.value}

@app.get("/workspaces/{ws}/metadata")
def get_metadata(ws: str):
    return {}

@app.post("/workspaces/{ws}/metadata")
def set_metadata(ws: str):
    return {}

# Search
@app.post("/workspaces/{ws}/search")
def search(ws: str, query: str = ""):
    conn = db()
    rows = conn.execute(
        "SELECT * FROM observations WHERE session_id IN (SELECT id FROM sessions WHERE workspace_id=?) AND content LIKE ? ORDER BY created_at DESC LIMIT 20",
        (ws, f"%{query}%")
    ).fetchall()
    conn.close()
    return {"items": [dict(r) for r in rows]}

# Queue / dream
@app.get("/workspaces/{ws}/queue")
def queue_status(ws: str):
    return {"status": "idle", "count": 0}

@app.post("/workspaces/{ws}/dream")
def schedule_dream(ws: str):
    return {"status": "scheduled"}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
