#!/usr/bin/env python3
"""
{{ project_name }} - Main Application
{{ description }}

Domain: {{ domain }}
Generated by ABI-Core CLI
"""

import os
import json
import asyncio
from datetime import datetime
from pathlib import Path
from typing import Dict, Any, List, Optional

import uvicorn
from fastapi import FastAPI, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel

from config.config import config
from abi_core.common.utils import abi_logging

# Lifespan context manager (replaces deprecated on_event)
from contextlib import asynccontextmanager

@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan - startup and shutdown"""
    
    # Startup
    abi_logging(f"🚀 Starting {{ project_name }}")
    abi_logging(f"📋 Description: {{ description }}")
    abi_logging(f"🏷️ Domain: {{ domain }}")
    abi_logging(f"⚙️ Configuration: {config.to_dict()}")
    
    {% if with_semantic_layer %}
    # Test semantic layer connection
    try:
        agents = await semantic_client.call("find_agent", query="list all")
        abi_logging(f"✅ Semantic layer connected - {len(agents)} agents registered")
    except Exception as e:
        abi_logging(f"⚠️ Semantic layer connection failed: {e}", level="warning")
    {% endif %}
    
    {% if with_guardian %}
    # Test guardian connection
    try:
        import httpx
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"http://{config.guardian_host}:{config.guardian_port}/health",
                timeout=5.0
            )
            if response.status_code == 200:
                abi_logging("✅ Guardian security service connected")
            else:
                abi_logging(f"⚠️ Guardian service returned {response.status_code}", level="warning")
    except Exception as e:
        abi_logging(f"⚠️ Guardian connection failed: {e}", level="warning")
    {% endif %}
    
    yield  # Application runs here
    
    # Shutdown
    abi_logging("🛑 Shutting down {{ project_name }}")

# FastAPI app with lifespan
app = FastAPI(
    title="{{ project_name }}",
    description="{{ description }}",
    version="{{ version | default('0.1.0') }}",
    docs_url="/docs",
    redoc_url="/redoc",
    lifespan=lifespan
)

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

# Pydantic models
class AgentRequest(BaseModel):
    query: str
    context: Optional[Dict[str, Any]] = None

class AgentResponse(BaseModel):
    agent_id: Optional[str]
    agent_name: Optional[str]
    response: str
    metadata: Dict[str, Any]

{% if with_semantic_layer %}
from abi_core.common.semantic_tools import MCPToolkit
from abi_core.common.service_card import ServiceCard

# Load service card for MCP authentication
_service_card_path = os.getenv(
    'SERVICE_CARD',
    str(Path(__file__).parent / 'service_cards' / 'webapp.json')
)
try:
    _service_card = ServiceCard.from_file(_service_card_path)
    abi_logging(f"✅ Service card loaded: {_service_card.name}")
except Exception as e:
    abi_logging(f"⚠️ No service card at {_service_card_path}: {e}", level="warning")
    _service_card = None

# Initialize semantic layer client via MCPToolkit with service identity
semantic_client = MCPToolkit(service_card=_service_card)
{% endif %}

{% if with_guardian %}
class GuardianClient:
    """Client for guardian security service"""
    
    def __init__(self):
        # guardian_host puede incluir http://, verificar para no duplicar
        if hasattr(config, 'guardian_url') and config.guardian_url:
            self.base_url = config.guardian_url
        else:
            if config.guardian_host.startswith('http://') or config.guardian_host.startswith('https://'):
                self.base_url = config.guardian_host
            else:
                self.base_url = f"http://{config.guardian_host}:{config.guardian_port}"
        
    async def validate_access(self, agent_id: str, agent_card: Dict[str, Any], 
                            request_metadata: Dict[str, Any] = None) -> Dict[str, Any]:
        """Validate agent access via Guardian"""
        import httpx
        
        try:
            async with httpx.AsyncClient() as client:
                response = await client.post(
                    f"{self.base_url}/v1/tools/validate_semantic_access",
                    json={
                        "agent_id": agent_id,
                        "agent_card": agent_card,
                        "request_metadata": request_metadata or {}
                    },
                    timeout=10.0
                )
                
                if response.status_code == 200:
                    return response.json()
                else:
                    abi_logging(f"Guardian error: {response.status_code}", level="error")
                    return {
                        "allowed": False,
                        "reason": f"Guardian service error: {response.status_code}",
                        "risk_score": 1.0
                    }
                    
        except Exception as e:
            abi_logging(f"Error contacting Guardian: {e}", level="error")
            return {
                "allowed": False,
                "reason": f"Guardian service unavailable: {str(e)}",
                "risk_score": 1.0
            }

# Initialize guardian client
guardian_client = GuardianClient()
{% endif %}

# Routes
@app.get("/")
async def root():
    """Root endpoint with service information"""
    return {
        "service": "{{ project_name }}",
        "description": "{{ description }}",
        "domain": "{{ domain }}",
        "version": "{{ version | default('0.1.0') }}",
        "status": "running",
        "timestamp": datetime.utcnow().isoformat(),
        "config": {
            "abi_role": config.abi_role,
            "abi_node": config.abi_node,
            "model_name": config.model_name,
            {% if with_semantic_layer %}
            "semantic_layer": f"{config.semantic_layer_host}:{config.semantic_layer_port}",
            {% endif %}
            {% if with_guardian %}
            "guardian_security": f"{config.guardian_host}:{config.guardian_port}",
            {% endif %}
        }
    }

@app.get("/health")
async def health():
    """Health check endpoint"""
    health_status = {
        "status": "healthy",
        "service": "{{ project_name }}",
        "timestamp": datetime.utcnow().isoformat(),
        "checks": {}
    }
    
    {% if with_semantic_layer %}
    # Check semantic layer
    try:
        agents = await semantic_client.call("find_agent", query="list all")
        health_status["checks"]["semantic_layer"] = {
            "status": "healthy",
            "registered_agents": len(agents)
        }
    except Exception as e:
        health_status["checks"]["semantic_layer"] = {
            "status": "unhealthy",
            "error": str(e)
        }
        health_status["status"] = "degraded"
    {% endif %}
    
    {% if with_guardian %}
    # Check guardian
    try:
        import httpx
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"http://{config.guardian_host}:{config.guardian_port}/v1/tools/get_guardian_status",
                timeout=5.0
            )
            if response.status_code == 200:
                health_status["checks"]["guardian"] = {
                    "status": "healthy",
                    "details": response.json()
                }
            else:
                health_status["checks"]["guardian"] = {
                    "status": "unhealthy",
                    "error": f"HTTP {response.status_code}"
                }
                health_status["status"] = "degraded"
    except Exception as e:
        health_status["checks"]["guardian"] = {
            "status": "unhealthy",
            "error": str(e)
        }
        health_status["status"] = "degraded"
    {% endif %}
    
    return health_status

@app.get("/v1/config")
async def get_config():
    """Get current configuration"""
    return config.to_dict()

{% if with_semantic_layer %}
@app.get("/v1/agents")
async def list_agents():
    """List all registered agents"""
    try:
        agents = await semantic_client.call("find_agent", query="list all")
        return {
            "agents": agents,
            "total": len(agents),
            "timestamp": datetime.utcnow().isoformat()
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error listing agents: {str(e)}")

@app.post("/v1/agents/find", response_model=AgentResponse)
async def find_agent(request: AgentRequest):
    """Find the best agent for a given query"""
    try:
        # Find agent via semantic layer
        agent_card = await semantic_client.call("find_agent", query=request.query)
        
        if not agent_card:
            return AgentResponse(
                agent_id=None,
                agent_name=None,
                response=f"No suitable agent found for query: {request.query}",
                metadata={
                    "query": request.query,
                    "found": False,
                    "timestamp": datetime.utcnow().isoformat()
                }
            )
        
        {% if with_guardian %}
        # Validate access via Guardian
        validation_result = await guardian_client.validate_access(
            agent_id=agent_card.get("id", "unknown"),
            agent_card=agent_card,
            request_metadata={
                "query": request.query,
                "method": "find_agent",
                "source_ip": "internal",
                "user_agent": "{{ project_name }}"
            }
        )
        
        if not validation_result.get("allowed", False):
            return AgentResponse(
                agent_id=agent_card.get("id"),
                agent_name=agent_card.get("name"),
                response=f"Access denied by Guardian: {validation_result.get('reason', 'Unknown reason')}",
                metadata={
                    "query": request.query,
                    "found": True,
                    "access_denied": True,
                    "risk_score": validation_result.get("risk_score", 1.0),
                    "guardian_validation": validation_result,
                    "timestamp": datetime.utcnow().isoformat()
                }
            )
        {% endif %}
        
        return AgentResponse(
            agent_id=agent_card.get("id"),
            agent_name=agent_card.get("name"),
            response=f"Found agent: {agent_card.get('name')} - {agent_card.get('description')}",
            metadata={
                "query": request.query,
                "found": True,
                "agent_card": agent_card,
                {% if with_guardian %}
                "guardian_validation": validation_result,
                {% endif %}
                "timestamp": datetime.utcnow().isoformat()
            }
        )
        
    except Exception as e:
        abi_logging(f"Error in find_agent: {e}", level="error")
        raise HTTPException(status_code=500, detail=f"Error finding agent: {str(e)}")
{% endif %}

{% if domain == 'finance' %}
@app.post("/v1/finance/analyze_risk")
async def analyze_financial_risk(request: dict):
    """Analyze financial risk for a scenario"""
    try:
        scenario = request.get("scenario", "")
        
        {% if with_semantic_layer %}
        # Find finance-specialized agent
        finance_query = f"financial risk analysis {scenario}"
        agent_card = await semantic_client.call("find_agent", query=finance_query)
        
        if not agent_card:
            raise HTTPException(status_code=404, detail="No suitable financial analysis agent found")
        
        {% if with_guardian %}
        # Validate with Guardian (finance-specific validation)
        validation_result = await guardian_client.validate_access(
            agent_id=agent_card.get("id", "unknown"),
            agent_card=agent_card,
            request_metadata={
                "tool_name": "analyze_financial_risk",
                "scenario": scenario,
                "compliance_verified": request.get("compliance_verified", False)
            }
        )
        
        if not validation_result.get("allowed", False):
            raise HTTPException(
                status_code=403, 
                detail=f"Access denied: {validation_result.get('reason', 'Unknown reason')}"
            )
        {% endif %}
        {% endif %}
        
        return {
            "scenario": scenario,
            {% if with_semantic_layer %}
            "recommended_agent": agent_card.get('name'),
            "agent_id": agent_card.get('id'),
            {% endif %}
            "risk_analysis_ready": True,
            "compliance_status": "verified" if request.get("compliance_verified") else "pending",
            "timestamp": datetime.utcnow().isoformat()
        }
        
    except HTTPException:
        raise
    except Exception as e:
        abi_logging(f"Error in financial risk analysis: {e}", level="error")
        raise HTTPException(status_code=500, detail=f"Error analyzing financial risk: {str(e)}")

@app.post("/v1/finance/compliance_check")
async def compliance_check(request: dict):
    """Check compliance for financial operations"""
    try:
        operation = request.get("operation", "")
        
        {% if with_semantic_layer %}
        # Find compliance agent
        compliance_query = f"compliance regulatory {operation}"
        agent_card = await semantic_client.call("find_agent", query=compliance_query)
        
        if not agent_card:
            raise HTTPException(status_code=404, detail="No suitable compliance agent found")
        {% endif %}
        
        return {
            "operation": operation,
            {% if with_semantic_layer %}
            "compliance_agent": agent_card.get('name'),
            "agent_id": agent_card.get('id'),
            {% endif %}
            "regulatory_ready": True,
            "compliance_framework": "{{ compliance_framework | default('SOX, GDPR') }}",
            "timestamp": datetime.utcnow().isoformat()
        }
        
    except HTTPException:
        raise
    except Exception as e:
        abi_logging(f"Error in compliance check: {e}", level="error")
        raise HTTPException(status_code=500, detail=f"Error checking compliance: {str(e)}")
{% elif domain == 'healthcare' %}
@app.post("/v1/healthcare/analyze_patient_data")
async def analyze_patient_data(request: dict):
    """Analyze patient data with HIPAA compliance"""
    try:
        data_type = request.get("data_type", "")
        patient_id = request.get("patient_id", "")
        
        {% if with_semantic_layer %}
        # Find healthcare agent
        healthcare_query = f"patient data analysis {data_type} HIPAA compliant"
        agent_card = await semantic_client.call("find_agent", query=healthcare_query)
        
        if not agent_card:
            raise HTTPException(status_code=404, detail="No suitable healthcare analysis agent found")
        
        {% if with_guardian %}
        # Validate with Guardian (healthcare-specific validation)
        validation_result = await guardian_client.validate_access(
            agent_id=agent_card.get("id", "unknown"),
            agent_card=agent_card,
            request_metadata={
                "tool_name": "patient_data_analysis",
                "patient_data": {"patient_id": patient_id, "data_type": data_type},
                "hipaa_compliant": True
            }
        )
        
        if not validation_result.get("allowed", False):
            raise HTTPException(
                status_code=403, 
                detail=f"Access denied: {validation_result.get('reason', 'Unknown reason')}"
            )
        {% endif %}
        {% endif %}
        
        return {
            "data_type": data_type,
            "patient_id": patient_id,
            {% if with_semantic_layer %}
            "healthcare_agent": agent_card.get('name'),
            "agent_id": agent_card.get('id'),
            {% endif %}
            "hipaa_compliant": True,
            "privacy_level": "high",
            "audit_required": True,
            "timestamp": datetime.utcnow().isoformat()
        }
        
    except HTTPException:
        raise
    except Exception as e:
        abi_logging(f"Error in patient data analysis: {e}", level="error")
        raise HTTPException(status_code=500, detail=f"Error analyzing patient data: {str(e)}")
{% endif %}

{% if with_guardian %}
@app.get("/v1/security/status")
async def get_security_status():
    """Get security status from Guardian"""
    try:
        import httpx
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"http://{config.guardian_host}:{config.guardian_port}/v1/tools/get_security_metrics",
                timeout=10.0
            )
            
            if response.status_code == 200:
                return response.json()
            else:
                raise HTTPException(status_code=response.status_code, detail="Guardian service error")
                
    except Exception as e:
        abi_logging(f"Error getting security status: {e}", level="error")
        raise HTTPException(status_code=500, detail=f"Error getting security status: {str(e)}")

@app.post("/v1/security/block_agent")
async def block_agent(request: dict):
    """Block an agent via Guardian"""
    try:
        agent_id = request.get("agent_id", "")
        reason = request.get("reason", "Manual block via API")
        
        if not agent_id:
            raise HTTPException(status_code=400, detail="agent_id is required")
        
        import httpx
        async with httpx.AsyncClient() as client:
            response = await client.post(
                f"http://{config.guardian_host}:{config.guardian_port}/v1/tools/block_agent",
                json={"agent_id": agent_id, "reason": reason},
                timeout=10.0
            )
            
            if response.status_code == 200:
                return response.json()
            else:
                raise HTTPException(status_code=response.status_code, detail="Guardian service error")
                
    except HTTPException:
        raise
    except Exception as e:
        abi_logging(f"Error blocking agent: {e}", level="error")
        raise HTTPException(status_code=500, detail=f"Error blocking agent: {str(e)}")
{% endif %}

def main():
    """Main entry point"""
    abi_logging(f"🌟 {{ project_name }} starting on {config.agent_host}:{config.agent_port}")
    
    uvicorn.run(
        "main:app",
        host=config.agent_host,
        port=config.agent_port,
        reload=config.debug,
        log_level=config.log_level.lower()
    )

if __name__ == "__main__":
    main()