#!/usr/bin/env python3
"""
Omi Webhook Receiver
Receives transcripts and memory data from Omi app in real-time.
Stores locally for Tony to access and learn from.
"""

import json
import os
from datetime import datetime
from pathlib import Path
from fastapi import FastAPI, Request, HTTPException, Security, Depends
from fastapi.responses import JSONResponse
from fastapi.security.api_key import APIKeyHeader
import uvicorn

app = FastAPI(title="Omi Webhook Receiver", version="1.0.0")

# Auth — token must match OMI_WEBHOOK_SECRET in .env
OMI_SECRET = os.environ.get("OMI_WEBHOOK_SECRET", "")
api_key_header = APIKeyHeader(name="X-Webhook-Secret", auto_error=False)

async def verify_token(request: Request):
    if not OMI_SECRET:
        return  # No secret configured — allow (dev mode)
    token = request.headers.get("X-Webhook-Secret") or request.query_params.get("secret")
    if token != OMI_SECRET:
        raise HTTPException(status_code=401, detail="Unauthorized")

# Storage paths
DATA_DIR = Path.home() / ".openclaw" / "workspace" / "omi-data"
TRANSCRIPTS_DIR = DATA_DIR / "transcripts"
MEMORIES_DIR = DATA_DIR / "memories"
RAW_DIR = DATA_DIR / "raw"

# Ensure directories exist
for d in [DATA_DIR, TRANSCRIPTS_DIR, MEMORIES_DIR, RAW_DIR]:
    d.mkdir(parents=True, exist_ok=True)


def save_raw(data: dict, event_type: str) -> str:
    """Save raw webhook payload for debugging"""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
    filename = f"{event_type}_{timestamp}.json"
    filepath = RAW_DIR / filename
    with open(filepath, "w") as f:
        json.dump(data, f, indent=2, default=str)
    return str(filepath)


def save_transcript(data: dict) -> str:
    """Save transcript data in organized format"""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    date_folder = TRANSCRIPTS_DIR / datetime.now().strftime("%Y-%m-%d")
    date_folder.mkdir(exist_ok=True)
    
    # Extract relevant fields
    transcript_data = {
        "received_at": datetime.now().isoformat(),
        "session_id": data.get("session_id"),
        "segments": data.get("segments", []),
        "transcript_segments": data.get("transcript_segments", []),
        "raw": data
    }
    
    filename = f"transcript_{timestamp}.json"
    filepath = date_folder / filename
    with open(filepath, "w") as f:
        json.dump(transcript_data, f, indent=2, default=str)
    
    return str(filepath)


def save_memory(data: dict) -> str:
    """Save memory/conversation summary"""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    date_folder = MEMORIES_DIR / datetime.now().strftime("%Y-%m-%d")
    date_folder.mkdir(exist_ok=True)
    
    memory_data = {
        "received_at": datetime.now().isoformat(),
        "memory_id": data.get("memory_id") or data.get("id"),
        "title": data.get("structured", {}).get("title") or data.get("title"),
        "overview": data.get("structured", {}).get("overview") or data.get("overview"),
        "action_items": data.get("structured", {}).get("action_items", []),
        "category": data.get("structured", {}).get("category"),
        "transcript": data.get("transcript"),
        "raw": data
    }
    
    filename = f"memory_{timestamp}.json"
    filepath = date_folder / filename
    with open(filepath, "w") as f:
        json.dump(memory_data, f, indent=2, default=str)
    
    return str(filepath)


@app.get("/")
async def root():
    """Health check endpoint"""
    return {
        "status": "ok",
        "service": "Omi Webhook Receiver",
        "version": "1.0.0",
        "storage": str(DATA_DIR)
    }


@app.post("/webhook")
async def receive_webhook(request: Request, _auth=Depends(verify_token)):
    """Main webhook endpoint for Omi"""
    try:
        data = await request.json()
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"Invalid JSON: {e}")
    
    # Log receipt
    print(f"[{datetime.now().isoformat()}] Webhook received")
    
    # Save raw data
    raw_path = save_raw(data, "webhook")
    
    # Determine type and save appropriately
    if "segments" in data or "transcript_segments" in data:
        filepath = save_transcript(data)
        event_type = "transcript"
    elif "structured" in data or "memory_id" in data:
        filepath = save_memory(data)
        event_type = "memory"
    else:
        filepath = raw_path
        event_type = "unknown"
    
    print(f"  Type: {event_type}")
    print(f"  Saved: {filepath}")
    
    return JSONResponse(
        content={
            "status": "received",
            "type": event_type,
            "saved_to": filepath
        },
        status_code=200
    )


@app.post("/webhook/transcript")
async def receive_transcript(request: Request, _auth=Depends(verify_token)):
    """Dedicated transcript endpoint"""
    try:
        data = await request.json()
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"Invalid JSON: {e}")
    
    print(f"[{datetime.now().isoformat()}] Transcript received")
    save_raw(data, "transcript")
    filepath = save_transcript(data)
    print(f"  Saved: {filepath}")
    
    return {"status": "received", "saved_to": filepath}


@app.post("/webhook/memory")
async def receive_memory(request: Request, _auth=Depends(verify_token)):
    """Dedicated memory endpoint"""
    try:
        data = await request.json()
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"Invalid JSON: {e}")
    
    print(f"[{datetime.now().isoformat()}] Memory received")
    save_raw(data, "memory")
    filepath = save_memory(data)
    
    # Extract summary for logging
    title = data.get("structured", {}).get("title") or data.get("title", "Untitled")
    print(f"  Title: {title}")
    print(f"  Saved: {filepath}")
    
    return {"status": "received", "saved_to": filepath}


@app.post("/webhook/realtime")
async def receive_realtime(request: Request, _auth=Depends(verify_token)):
    """Real-time streaming endpoint"""
    try:
        data = await request.json()
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"Invalid JSON: {e}")
    
    # Don't save every realtime segment to avoid spam
    # Just acknowledge
    segment_text = data.get("text", "")[:50]
    print(f"[RT] {segment_text}...")
    
    return {"status": "received"}


if __name__ == "__main__":
    print("=" * 50)
    print("Omi Webhook Receiver")
    print(f"Data directory: {DATA_DIR}")
    print("=" * 50)
    uvicorn.run(app, host="0.0.0.0", port=8765)
