"""
FastAPI Application for AI Knowledge Hub

On-demand web server with automatic 30-minute idle timeout.
Provides REST API for knowledge management operations.
"""

import os
import sys
import time
import threading
from typing import Dict, Any, List, Optional

from fastapi import FastAPI, HTTPException, Query, Request
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel

# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from core.knowledge_manager import KnowledgeManager
from core.exporter import export_knowledge_pack, get_export_preview
from core.importer import import_knowledge_pack


# Configuration
IDLE_TIMEOUT = 30 * 60  # 30 minutes in seconds
last_activity = time.time()


# FastAPI app
app = FastAPI(
    title="AI Knowledge Hub",
    description="On-demand knowledge management API with automatic idle timeout",
    version="1.0.0"
)

# CORS middleware for local development
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Try to mount Web UI (optional component)
try:
    from thinkbank.webui import mount_webui, is_available

    if is_available():
        mount_webui(app)
        print("✓ Web UI mounted at http://localhost:8765/")
    else:
        print("⚠ Web UI dependencies not installed (optional)")

        @app.get("/")
        async def root_fallback():
            return {
                "message": "AI Knowledge Hub API",
                "version": "1.0.0",
                "docs": "/docs",
                "note": "Web UI not available. Install dependencies or use CLI."
            }
except ImportError:
    print("⚠ Web UI module not found (optional)")

    @app.get("/")
    async def root_fallback():
        return {
            "message": "AI Knowledge Hub API",
            "version": "1.0.0",
            "docs": "/docs",
            "note": "Web UI not available. Install dependencies or use CLI."
        }


# Auto-timeout mechanism
def check_idle_timeout():
    """Background thread to check for idle timeout and shutdown."""
    global last_activity

    while True:
        time.sleep(60)  # Check every minute
        idle_time = time.time() - last_activity

        if idle_time > IDLE_TIMEOUT:
            print(f"\n⏱ Idle timeout reached ({idle_time/60:.1f} minutes)")
            print("Shutting down server...")
            os._exit(0)  # Force exit


# Start background timeout checker
timeout_thread = threading.Thread(target=check_idle_timeout, daemon=True)
timeout_thread.start()


@app.middleware("http")
async def update_activity(request, call_next):
    """Update last activity time on each request."""
    global last_activity
    last_activity = time.time()
    response = await call_next(request)
    return response


# Pydantic models for request validation
class ExportRequest(BaseModel):
    output_path: str
    filter_criteria: Optional[Dict[str, Any]] = None
    format: str = "json"
    metadata: Optional[Dict[str, Any]] = None


class ImportRequest(BaseModel):
    pack_path: str
    conflict_resolution: str = "ask"
    dry_run: bool = False


# API Endpoints

@app.get("/health")
async def health_check():
    """Health check endpoint."""
    uptime = time.time() - (last_activity - IDLE_TIMEOUT + (time.time() - last_activity))
    return {
        "status": "healthy",
        "uptime": int(time.time() - (last_activity - (time.time() - last_activity))),
        "idle_timeout": IDLE_TIMEOUT,
        "idle_remaining": int(IDLE_TIMEOUT - (time.time() - last_activity))
    }


@app.get("/api/knowledge")
async def list_knowledge(
    type: Optional[str] = Query(None, description="Filter by knowledge type"),
    min_score: Optional[float] = Query(None, description="Minimum score threshold"),
    tags: Optional[str] = Query(None, description="Comma-separated tags"),
    limit: int = Query(100, description="Maximum number of items")
):
    """
    List knowledge items with optional filters.

    Args:
        type: Knowledge type (skill, rule, pattern, domain, user, lesson)
        min_score: Minimum score threshold
        tags: Comma-separated list of tags
        limit: Maximum number of items to return

    Returns:
        List of knowledge items
    """
    try:
        km = KnowledgeManager()

        # Parse tags
        tags_list = [t.strip() for t in tags.split(',')] if tags else None

        items = km.list(
            knowledge_type=type,
            min_score=min_score,
            tags=tags_list,
            limit=limit
        )

        # Format items for API response
        formatted_items = []
        for item in items:
            fm = item['frontmatter']
            formatted_items.append({
                "id": fm.get('id'),
                "type": fm.get('type'),
                "title": fm.get('title'),
                "score": fm.get('score', 0.0),
                "tags": fm.get('tags', []),
                "keywords": fm.get('keywords', []),
                "created": fm.get('created'),
                "updated": fm.get('updated'),
                "file_path": item.get('file_path')
            })

        return {
            "success": True,
            "count": len(formatted_items),
            "items": formatted_items
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.get("/api/knowledge/{knowledge_id}")
async def get_knowledge(knowledge_id: str):
    """
    Get a single knowledge item by ID.

    Args:
        knowledge_id: Knowledge item ID

    Returns:
        Knowledge item with frontmatter and content
    """
    try:
        km = KnowledgeManager()
        item = km.read(knowledge_id)

        if not item:
            raise HTTPException(status_code=404, detail="Knowledge item not found")

        return {
            "success": True,
            "item": {
                "frontmatter": item['frontmatter'],
                "content": item['content'],
                "file_path": item['file_path']
            }
        }

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.get("/api/search")
async def search_knowledge(
    query: str = Query(..., description="Search query"),
    type: Optional[str] = Query(None, description="Filter by knowledge type"),
    search_content: bool = Query(True, description="Search in content")
):
    """
    Search knowledge items by keyword.

    Args:
        query: Search query string
        type: Optional knowledge type filter
        search_content: Whether to search in content (default: true)

    Returns:
        List of matching knowledge items
    """
    try:
        km = KnowledgeManager()

        items = km.search(
            query=query,
            knowledge_type=type,
            search_content=search_content
        )

        # Format items
        formatted_items = []
        for item in items:
            fm = item['frontmatter']
            formatted_items.append({
                "id": fm.get('id'),
                "type": fm.get('type'),
                "title": fm.get('title'),
                "score": fm.get('score', 0.0),
                "tags": fm.get('tags', []),
                "match_type": item.get('match_type', 'unknown')
            })

        return {
            "success": True,
            "count": len(formatted_items),
            "query": query,
            "items": formatted_items
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.post("/api/export")
async def export_knowledge(request: ExportRequest):
    """
    Export knowledge pack to .khb file.

    Request body:
        - output_path: Path to output file
        - filter_criteria: Optional filters (type, min_score, tags, limit)
        - format: json or yaml
        - metadata: Optional pack metadata (name, author, description)

    Returns:
        Export summary with count, path, size
    """
    try:
        result = export_knowledge_pack(
            output_path=request.output_path,
            filter_criteria=request.filter_criteria,
            format=request.format,
            metadata=request.metadata
        )

        return result

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.get("/api/export/preview")
async def preview_export(
    type: Optional[str] = Query(None),
    min_score: Optional[float] = Query(None),
    tags: Optional[str] = Query(None),
    limit: Optional[int] = Query(None)
):
    """
    Preview export without actually exporting.

    Args:
        type: Knowledge type filter
        min_score: Minimum score filter
        tags: Comma-separated tags
        limit: Maximum number of items

    Returns:
        Preview with count, type breakdown, estimated size
    """
    try:
        # Build filter criteria
        filter_criteria = {}
        if type:
            filter_criteria['type'] = type
        if min_score:
            filter_criteria['min_score'] = min_score
        if tags:
            filter_criteria['tags'] = [t.strip() for t in tags.split(',')]
        if limit:
            filter_criteria['limit'] = limit

        preview = get_export_preview(filter_criteria if filter_criteria else None)

        return {
            "success": True,
            **preview
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.post("/api/import")
async def import_knowledge(request: ImportRequest):
    """
    Import knowledge from .khb file.

    Request body:
        - pack_path: Path to .khb file
        - conflict_resolution: skip, overwrite, merge, rename, or ask
        - dry_run: Preview without importing

    Returns:
        Import summary with imported, skipped, conflicts, errors
    """
    try:
        result = import_knowledge_pack(
            pack_path=request.pack_path,
            conflict_resolution=request.conflict_resolution,
            dry_run=request.dry_run
        )

        return result

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.get("/api/stats")
async def get_stats():
    """
    Get knowledge base statistics.

    Returns:
        Statistics including counts by type, average scores, etc.
    """
    try:
        km = KnowledgeManager()

        # Get all items
        all_items = km.list()

        # Calculate statistics
        type_counts = {}
        total_score = 0.0
        high_value_count = 0  # Score >= 0.7

        for item in all_items:
            fm = item['frontmatter']
            ktype = fm.get('type', 'unknown')
            score = fm.get('score', 0.0)

            type_counts[ktype] = type_counts.get(ktype, 0) + 1
            total_score += score

            if score >= 0.7:
                high_value_count += 1

        avg_score = total_score / len(all_items) if all_items else 0.0

        return {
            "success": True,
            "stats": {
                "total_items": len(all_items),
                "type_counts": type_counts,
                "average_score": round(avg_score, 2),
                "high_value_items": high_value_count,
                "high_value_percentage": round((high_value_count / len(all_items) * 100) if all_items else 0, 1)
            }
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


# Run with: uvicorn server.app:app --reload --port 8765
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8765)
