#!/usr/bin/env python3
"""
Eden Meta-Learning API
Production REST API for MCL, Transfer Map, and Causal Tester

Endpoints:
  POST /api/reason        - Get strategic reasoning advice
  POST /api/transfer      - Transfer knowledge across domains
  POST /api/test          - Test causal hypothesis
  GET  /api/status        - System status
  GET  /api/health        - Health check
"""

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any
import sys
import logging

# Add paths
sys.path.append('/Eden/CORE/phi_fractal/meta_cognition')
sys.path.append('/Eden/CORE/phi_fractal/transfer_embedding')
sys.path.append('/Eden/CORE/phi_fractal/sandbox_envs')

from meta_loop import MetaCognitionLoop, Observation, BeliefState
from transfer_map import TransferMap, Concept
from causal_tester import CausalTester, Hypothesis

# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Initialize FastAPI
app = FastAPI(
    title="Eden Meta-Learning API",
    description="Production API for Eden's meta-learning systems",
    version="1.0.0"
)

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

# Initialize systems (singletons)
mcl = MetaCognitionLoop()
transfer_map = TransferMap()
causal_tester = CausalTester()

logger.info("🚀 Eden API initialized - all systems operational")


# ============================================================================
# REQUEST/RESPONSE MODELS
# ============================================================================

class ReasonRequest(BaseModel):
    problem: str = Field(..., description="Problem to solve")
    task_type: Optional[str] = Field("general", description="Type of task")
    complexity: float = Field(0.5, ge=0.0, le=1.0, description="Problem complexity")
    relevant_schemas: List[str] = Field(default_factory=list, description="Relevant schemas")

class ReasonResponse(BaseModel):
    chosen_strategy: str
    confidence: float
    success: bool
    reasoning_trace: List[str]
    meta_learning_active: bool = True

class ConceptRequest(BaseModel):
    name: str
    domain: str
    description: str
    properties: List[str]
    examples: List[str]

class TransferRequest(BaseModel):
    source_concept: str = Field(..., description="e.g., 'python:recursion'")
    target_domain: str = Field(..., description="e.g., 'javascript'")

class TransferResponse(BaseModel):
    source_concept: str
    source_domain: str
    target_domain: str
    confidence: float
    analogies: List[str]
    success: bool
    transferred_knowledge: Dict[str, Any]

class HypothesisRequest(BaseModel):
    id: str
    description: str
    intervention: str
    expected_effect: str
    variables: Dict[str, Any]
    n_trials: int = Field(10, ge=1, le=100)

class HypothesisResponse(BaseModel):
    hypothesis_id: str
    causal_relation: str
    effect_size: float
    confidence: float
    evidence_strength: float
    control_outcome: float
    intervention_outcome: float


# ============================================================================
# ENDPOINTS
# ============================================================================

@app.get("/")
async def root():
    """Root endpoint"""
    return {
        "service": "Eden Meta-Learning API",
        "version": "1.0.0",
        "status": "operational",
        "docs": "/docs",
        "systems": {
            "meta_cognition": "operational",
            "transfer_map": "operational",
            "causal_tester": "operational"
        }
    }

@app.get("/api/health")
async def health():
    """Health check"""
    return {
        "status": "healthy",
        "systems": {
            "mcl": "operational",
            "transfer_map": "operational",
            "causal_tester": "operational"
        }
    }


# ============================================================================
# META-COGNITION ENDPOINTS
# ============================================================================

@app.post("/api/reason", response_model=ReasonResponse)
async def reason(request: ReasonRequest):
    """
    Get strategic reasoning advice from Eden
    
    Eden uses her meta-learning to choose the best reasoning strategy
    for your problem based on 95+ episodes of experience.
    """
    try:
        obs = Observation(
            content=request.problem,
            task_type=request.task_type,
            complexity=request.complexity
        )
        
        belief = BeliefState(
            confidence=0.6,
            relevant_schemas=request.relevant_schemas
        )
        
        result = mcl.process(obs, belief, n_candidates=3)
        
        return ReasonResponse(
            chosen_strategy=result['chosen_strategy'],
            confidence=result['confidence'],
            success=result['success'],
            reasoning_trace=result['reasoning_trace']
        )
    except Exception as e:
        logger.error(f"Reasoning error: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@app.get("/api/mcl/status")
async def mcl_status():
    """Get meta-cognition loop status"""
    try:
        report = mcl.meta_policy.get_report()
        
        # Get top 5 strategies
        top_strategies = sorted(
            report['strategies'].items(),
            key=lambda x: x[1]['weight'],
            reverse=True
        )[:5]
        
        return {
            "total_episodes": report['total_episodes'],
            "top_strategies": [
                {
                    "name": name,
                    "weight": stats['weight'],
                    "count": stats['count'],
                    "success_rate": stats['success_rate']
                }
                for name, stats in top_strategies
            ],
            "status": "operational"
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


# ============================================================================
# TRANSFER MAP ENDPOINTS
# ============================================================================

@app.post("/api/transfer/learn")
async def learn_concept(request: ConceptRequest):
    """Teach Eden a new concept"""
    try:
        concept = Concept(
            name=request.name,
            domain=request.domain,
            description=request.description,
            properties=request.properties,
            examples=request.examples
        )
        
        learned = transfer_map.learn_concept(concept)
        
        return {
            "concept": f"{learned.domain}:{learned.name}",
            "embedding_shape": learned.embedding.shape if learned.embedding is not None else None,
            "success": True
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.post("/api/transfer", response_model=TransferResponse)
async def transfer_knowledge(request: TransferRequest):
    """
    Transfer knowledge from one domain to another
    
    Example: Transfer "recursion" from Python to JavaScript
    """
    try:
        result = transfer_map.transfer_to_domain(
            request.source_concept,
            request.target_domain
        )
        
        return TransferResponse(
            source_concept=result.source_concept,
            source_domain=result.source_domain,
            target_domain=result.target_domain,
            confidence=result.confidence,
            analogies=result.analogies,
            success=result.success,
            transferred_knowledge=result.transferred_knowledge
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.get("/api/transfer/status")
async def transfer_status():
    """Get transfer map status"""
    try:
        report = transfer_map.get_transfer_report()
        return {
            **report,
            "status": "operational"
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


# ============================================================================
# CAUSAL TESTER ENDPOINTS
# ============================================================================

@app.post("/api/test", response_model=HypothesisResponse)
async def test_hypothesis(request: HypothesisRequest):
    """
    Test a causal hypothesis in safe sandbox
    
    Eden will run controlled experiments to validate your hypothesis
    """
    try:
        # Create hypothesis
        hyp = Hypothesis(
            id=request.id,
            description=request.description,
            intervention=request.intervention,
            expected_effect=request.expected_effect,
            variables=request.variables
        )
        
        # Propose and test
        causal_tester.propose_hypothesis(hyp)
        experiment = causal_tester.test_hypothesis(request.id, n_trials=request.n_trials)
        
        return HypothesisResponse(
            hypothesis_id=experiment.hypothesis_id,
            causal_relation=experiment.causal_relation.value,
            effect_size=experiment.effect_size,
            confidence=experiment.confidence,
            evidence_strength=experiment.evidence_strength,
            control_outcome=experiment.control_outcome,
            intervention_outcome=experiment.intervention_outcome
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.get("/api/causal/status")
async def causal_status():
    """Get causal tester status"""
    try:
        report = causal_tester.get_causal_report()
        return {
            **report,
            "status": "operational"
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


# ============================================================================
# INTEGRATED ENDPOINT
# ============================================================================

@app.post("/api/solve")
async def solve_problem(request: ReasonRequest):
    """
    Complete problem-solving pipeline
    
    Uses all three systems:
    1. Causal testing (if applicable)
    2. Transfer learning (find similar)
    3. Strategic reasoning (choose approach)
    """
    try:
        # Step 1: Strategic reasoning
        obs = Observation(
            content=request.problem,
            task_type=request.task_type,
            complexity=request.complexity
        )
        
        belief = BeliefState(
            confidence=0.6,
            relevant_schemas=request.relevant_schemas
        )
        
        reasoning_result = mcl.process(obs, belief, n_candidates=3)
        
        return {
            "problem": request.problem,
            "chosen_strategy": reasoning_result['chosen_strategy'],
            "confidence": reasoning_result['confidence'],
            "reasoning_trace": reasoning_result['reasoning_trace'],
            "systems_used": ["meta_cognition"],
            "recommendation": f"Use {reasoning_result['chosen_strategy']} strategy"
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.get("/api/status")
async def full_status():
    """Complete system status"""
    try:
        mcl_report = mcl.meta_policy.get_report()
        transfer_report = transfer_map.get_transfer_report()
        causal_report = causal_tester.get_causal_report()
        
        return {
            "status": "operational",
            "version": "1.0.0",
            "systems": {
                "meta_cognition": {
                    "total_episodes": mcl_report['total_episodes'],
                    "top_strategy": max(
                        mcl_report['strategies'].items(),
                        key=lambda x: x[1]['weight']
                    )[0] if mcl_report['strategies'] else None,
                    "status": "operational"
                },
                "transfer_map": {
                    **transfer_report,
                    "status": "operational"
                },
                "causal_tester": {
                    **causal_report,
                    "status": "operational"
                }
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


# ============================================================================
# MAIN
# ============================================================================

if __name__ == "__main__":
    import uvicorn
    
    print("\n" + "=" * 70)
    print("🚀 EDEN META-LEARNING API")
    print("=" * 70)
    print("\n📍 Starting server...")
    print("   URL: http://localhost:8092")
    print("   Docs: http://localhost:8092/docs")
    print("   Interactive: http://localhost:8092/redoc")
    print("\n✨ All systems operational!\n")
    
    uvicorn.run(app, host="0.0.0.0", port=8092, log_level="info")
