#!/usr/bin/env python3
"""
Genesis Command Bridge - Directive Poller

Polls PostgreSQL for new directives from Kinan (via AIVA voice calls)
and displays them in the terminal. Designed to run as a background task
in Claude Code.

Usage:
    # Run continuously (polls every 30 seconds):
    python poll_directives.py

    # Single poll (check once and exit):
    python poll_directives.py --once

    # Custom interval:
    python poll_directives.py --interval 15

    # Post a status update back to Kinan:
    python poll_directives.py --post-status "Swarm complete: 195/200 succeeded"
"""

import os
import sys
import json
import time
import argparse
import signal
from datetime import datetime, timezone

import psycopg2
import psycopg2.extras

# ---------------------------------------------------------------------------
# Configuration (Elestio PostgreSQL)
# ---------------------------------------------------------------------------

PG_HOST = os.environ.get("GENESIS_POSTGRES_HOST", "postgresql-genesis-u50607.vm.elestio.app")
PG_PORT = int(os.environ.get("GENESIS_POSTGRES_PORT", "25432"))
PG_USER = os.environ.get("GENESIS_POSTGRES_USER", "postgres")
PG_PASS = os.environ.get("GENESIS_POSTGRES_PASSWORD", "CiBjh6LM7Yuqkq-jo2r7eQDw")
PG_DB = os.environ.get("GENESIS_POSTGRES_DATABASE", "postgres")

POLL_INTERVAL = 30  # seconds

# Priority display formatting
PRIORITY_DISPLAY = {
    "urgent": "\033[91;1m[URGENT]\033[0m",
    "high":   "\033[93;1m[HIGH]\033[0m",
    "normal": "\033[92m[NORMAL]\033[0m",
    "low":    "\033[90m[LOW]\033[0m",
}

running = True


def signal_handler(sig, frame):
    global running
    running = False
    print("\n[BRIDGE] Shutting down poller...")


signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)


# ---------------------------------------------------------------------------
# Database
# ---------------------------------------------------------------------------

def get_connection():
    """Create a new PostgreSQL connection."""
    return psycopg2.connect(
        host=PG_HOST,
        port=PG_PORT,
        user=PG_USER,
        password=PG_PASS,
        database=PG_DB,
    )


def ensure_schema(conn):
    """Ensure the genesis_bridge schema and table exist."""
    cur = conn.cursor()
    cur.execute("""
        CREATE SCHEMA IF NOT EXISTS genesis_bridge;

        CREATE TABLE IF NOT EXISTS genesis_bridge.command_queue (
            id SERIAL PRIMARY KEY,
            direction TEXT NOT NULL CHECK (direction IN ('kinan_to_claude', 'claude_to_kinan')),
            message TEXT NOT NULL,
            priority TEXT DEFAULT 'normal' CHECK (priority IN ('low', 'normal', 'high', 'urgent')),
            status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'read', 'executed', 'acknowledged')),
            source TEXT DEFAULT 'aiva_voice',
            created_at TIMESTAMPTZ DEFAULT NOW(),
            read_at TIMESTAMPTZ,
            executed_at TIMESTAMPTZ,
            response TEXT,
            metadata JSONB DEFAULT '{}'
        );

        CREATE INDEX IF NOT EXISTS idx_command_queue_pending
            ON genesis_bridge.command_queue(direction, status)
            WHERE status = 'pending';
    """)
    conn.commit()
    cur.close()


# ---------------------------------------------------------------------------
# Core Functions
# ---------------------------------------------------------------------------

def poll_for_directives(conn) -> list:
    """
    Fetch and mark as 'read' all pending directives from Kinan.
    Returns list of directive dicts.
    """
    cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
    cur.execute("""
        UPDATE genesis_bridge.command_queue
        SET status = 'read', read_at = NOW()
        WHERE direction = 'kinan_to_claude' AND status = 'pending'
        RETURNING id, message, priority, created_at, source, metadata
    """)
    rows = cur.fetchall()
    conn.commit()
    cur.close()
    return rows


def post_status_update(conn, message: str, priority: str = "normal") -> int:
    """
    Post a status update from Claude to Kinan.
    Returns the message ID.
    """
    cur = conn.cursor()
    cur.execute("""
        INSERT INTO genesis_bridge.command_queue
        (direction, message, priority, source)
        VALUES ('claude_to_kinan', %s, %s, 'claude_terminal')
        RETURNING id
    """, (message, priority))
    msg_id = cur.fetchone()[0]
    conn.commit()
    cur.close()
    return msg_id


def mark_executed(conn, directive_id: int, response: str = None):
    """Mark a directive as executed."""
    cur = conn.cursor()
    cur.execute("""
        UPDATE genesis_bridge.command_queue
        SET status = 'executed', executed_at = NOW(), response = %s
        WHERE id = %s
    """, (response, directive_id))
    conn.commit()
    cur.close()


def display_directive(directive: dict):
    """Pretty-print a directive to the terminal."""
    pri = PRIORITY_DISPLAY.get(directive["priority"], "[???]")
    ts = directive["created_at"]
    if hasattr(ts, "strftime"):
        ts = ts.strftime("%H:%M:%S")

    print()
    print("=" * 70)
    print(f"  KINAN DIRECTIVE #{directive['id']} {pri}")
    print(f"  Time: {ts}  |  Source: {directive.get('source', 'aiva_voice')}")
    print(f"  " + "-" * 66)
    print(f"  {directive['message']}")
    print("=" * 70)
    print()


# ---------------------------------------------------------------------------
# Main Loop
# ---------------------------------------------------------------------------

def main():
    parser = argparse.ArgumentParser(description="Genesis Command Bridge Poller")
    parser.add_argument("--once", action="store_true", help="Poll once and exit")
    parser.add_argument("--interval", type=int, default=POLL_INTERVAL, help="Poll interval in seconds")
    parser.add_argument("--post-status", type=str, help="Post a status update to Kinan and exit")
    parser.add_argument("--priority", type=str, default="normal", help="Priority for --post-status")
    args = parser.parse_args()

    conn = get_connection()
    ensure_schema(conn)

    # Post status mode
    if args.post_status:
        msg_id = post_status_update(conn, args.post_status, args.priority)
        print(f"[BRIDGE] Status update #{msg_id} posted for Kinan: {args.post_status}")
        conn.close()
        return

    # Polling mode
    print("[BRIDGE] Genesis Command Bridge Poller starting...")
    print(f"[BRIDGE] Polling every {args.interval}s for Kinan's directives")
    print(f"[BRIDGE] Database: {PG_HOST}:{PG_PORT}/{PG_DB}")
    print("[BRIDGE] Waiting for directives... (Ctrl+C to stop)")
    print()

    total_received = 0

    while running:
        try:
            # Reconnect if connection is closed
            if conn.closed:
                conn = get_connection()

            directives = poll_for_directives(conn)

            for d in directives:
                display_directive(d)
                total_received += 1

            if args.once:
                if not directives:
                    print("[BRIDGE] No pending directives.")
                break

            time.sleep(args.interval)

        except psycopg2.OperationalError as e:
            print(f"[BRIDGE] Database connection lost: {e}")
            print("[BRIDGE] Reconnecting in 10s...")
            time.sleep(10)
            try:
                conn = get_connection()
            except Exception:
                pass

        except Exception as e:
            print(f"[BRIDGE] Error: {e}")
            time.sleep(5)

    print(f"[BRIDGE] Poller stopped. Total directives received: {total_received}")
    if not conn.closed:
        conn.close()


if __name__ == "__main__":
    main()
