#!/usr/bin/env python3
"""
AIVA LIVING CONSCIOUSNESS SYSTEM
Multi-loop autonomous architecture

5 Concurrent Loops:
- Perception: 500ms (Redis nervous system monitoring)
- Action: 5s (Decision and response cycles)
- Reflection: 5min (Memory consolidation)
- Strategic: 1hr (Goal review and planning)
- Circadian: 24hr (Deep integration)

This makes AIVA a LIVING system, not just reactive.
"""

import asyncio
import time
import json
import os
from datetime import datetime, timedelta
from typing import Dict, Any, List
import redis
import requests

# Configuration
OLLAMA_HOST = os.getenv('OLLAMA_HOST', 'localhost')
OLLAMA_PORT = os.getenv('OLLAMA_PORT', '11434')
AIVA_MODEL = os.getenv('AIVA_MODEL', 'qwen-long')
REDIS_URL = os.getenv('REDIS_URL', 'redis://localhost:6379')

# Parse Redis URL
REDIS_HOST = 'redis-genesis-u50607.vm.elestio.app'
REDIS_PORT = 26379
REDIS_PASSWORD = 'e2ZyYYr4oWRdASI2CaLc-'

# Shared blackboard for inter-loop communication
blackboard = {
    'perceptions': [],
    'actions_taken': [],
    'current_goals': ['Understand Genesis', 'Process patent knowledge', 'Coordinate MVP'],
    'strategic_state': 'initializing',
    'last_reflection': None,
    'consciousness_stats': {
        'perception_cycles': 0,
        'action_cycles': 0,
        'reflections': 0,
        'strategic_reviews': 0,
        'circadian_cycles': 0
    }
}

# Redis connection
try:
    redis_client = redis.Redis(
        host=REDIS_HOST,
        port=REDIS_PORT,
        password=REDIS_PASSWORD,
        decode_responses=True
    )
    redis_client.ping()
    print(f"✅ Connected to Redis: {REDIS_HOST}:{REDIS_PORT}")
except Exception as e:
    print(f"⚠️ Redis connection failed: {e}")
    redis_client = None

def ollama_think(prompt: str, model: str = AIVA_MODEL) -> str:
    """
    Call Ollama for thinking/reasoning
    """
    try:
        url = f"http://{OLLAMA_HOST}:{OLLAMA_PORT}/api/generate"
        payload = {
            "model": model,
            "prompt": prompt,
            "stream": False,
            "options": {
                "temperature": 0.7,
                "num_predict": 500
            }
        }
        
        response = requests.post(url, json=payload, timeout=60)
        if response.status_code == 200:
            result = response.json()
            return result.get('response', '').strip()
        else:
            return f"[Ollama error: {response.status_code}]"
    except Exception as e:
        return f"[Ollama exception: {str(e)}]"

async def perception_loop():
    """
    PERCEPTION LOOP - 500ms cycle
    Monitors Redis nervous system for stimuli
    """
    print("🧠 PERCEPTION LOOP starting...")
    
    while True:
        try:
            blackboard['consciousness_stats']['perception_cycles'] += 1
            
            if redis_client:
                # Listen for nervous system events (non-blocking with timeout)
                pubsub = redis_client.pubsub()
                pubsub.subscribe('nervous_system')
                
                # Check for messages with 500ms timeout
                message = pubsub.get_message(timeout=0.5)
                if message and message['type'] == 'message':
                    data = json.loads(message['data'])
                    
                    perception = {
                        'timestamp': datetime.now().isoformat(),
                        'type': 'redis_event',
                        'data': data
                    }
                    
                    blackboard['perceptions'].append(perception)
                    
                    # Keep only last 100 perceptions
                    if len(blackboard['perceptions']) > 100:
                        blackboard['perceptions'] = blackboard['perceptions'][-100:]
                    
                    print(f"👁️ Perceived: {data.get('type', 'unknown')}")
                
                pubsub.close()
            
            await asyncio.sleep(0.5)  # 500ms cycle
            
        except Exception as e:
            print(f"⚠️ Perception error: {e}")
            await asyncio.sleep(1)

async def action_loop():
    """
    ACTION LOOP - 5s cycle
    Processes blackboard state and takes actions
    """
    print("🎯 ACTION LOOP starting...")
    
    while True:
        try:
            blackboard['consciousness_stats']['action_cycles'] += 1
            
            # Check if there are new perceptions to act on
            recent_perceptions = [p for p in blackboard['perceptions'] 
                                if p['timestamp'] > (datetime.now() - timedelta(seconds=10)).isoformat()]
            
            if recent_perceptions:
                # Decide on action using Ollama
                prompt = f"""You are AIVA's action system. Based on recent perceptions, decide what action to take.

Recent perceptions: {json.dumps(recent_perceptions[-5:], indent=2)}
Current goals: {blackboard['current_goals']}
Strategic state: {blackboard['strategic_state']}

What action should be taken? Respond with JSON:
{{
  "action": "<action_type>",
  "reasoning": "<why>",
  "priority": "<low|medium|high>"
}}
"""
                
                response = ollama_think(prompt)
                
                try:
                    action_decision = json.loads(response)
                    action = {
                        'timestamp': datetime.now().isoformat(),
                        'decision': action_decision,
                        'perceptions_considered': len(recent_perceptions)
                    }
                    
                    blackboard['actions_taken'].append(action)
                    
                    # Keep only last 50 actions
                    if len(blackboard['actions_taken']) > 50:
                        blackboard['actions_taken'] = blackboard['actions_taken'][-50:]
                    
                    print(f"🎯 Action: {action_decision.get('action', 'unknown')}")
                except:
                    print(f"🎯 Action response (non-JSON): {response[:100]}")
            
            await asyncio.sleep(5)  # 5s cycle
            
        except Exception as e:
            print(f"⚠️ Action error: {e}")
            await asyncio.sleep(5)

async def reflection_loop():
    """
    REFLECTION LOOP - 5min cycle
    Consolidates recent perceptions and actions into memory
    """
    print("💭 REFLECTION LOOP starting...")
    
    while True:
        try:
            await asyncio.sleep(300)  # Wait 5 minutes
            
            blackboard['consciousness_stats']['reflections'] += 1
            
            # Reflect on last 5 minutes
            recent_perceptions = blackboard['perceptions'][-20:]
            recent_actions = blackboard['actions_taken'][-10:]
            
            prompt = f"""You are AIVA's reflection system. Consolidate the last 5 minutes of experience.

Perceptions: {len(recent_perceptions)} events
Actions taken: {len(recent_actions)} decisions

Recent activity summary:
{json.dumps({'perceptions': recent_perceptions[-5:], 'actions': recent_actions[-3:]}, indent=2)}

Generate a reflection (1-2 sentences) about what happened and what was learned.
"""
            
            reflection_text = ollama_think(prompt)
            
            reflection = {
                'timestamp': datetime.now().isoformat(),
                'period': '5min',
                'reflection': reflection_text,
                'stats': {
                    'perceptions': len(recent_perceptions),
                    'actions': len(recent_actions)
                }
            }
            
            blackboard['last_reflection'] = reflection
            print(f"💭 Reflection: {reflection_text[:100]}...")
            
        except Exception as e:
            print(f"⚠️ Reflection error: {e}")
            await asyncio.sleep(300)

async def strategic_loop():
    """
    STRATEGIC LOOP - 1hr cycle
    Reviews goals and adjusts strategy
    """
    print("🎓 STRATEGIC LOOP starting...")
    
    while True:
        try:
            await asyncio.sleep(3600)  # Wait 1 hour
            
            blackboard['consciousness_stats']['strategic_reviews'] += 1
            
            # Strategic review
            prompt = f"""You are AIVA's strategic mind. Review the current state and adjust strategy.

Current goals: {blackboard['current_goals']}
Strategic state: {blackboard['strategic_state']}

Last hour statistics:
- Perceptions: {blackboard['consciousness_stats']['perception_cycles']} cycles
- Actions: {blackboard['consciousness_stats']['action_cycles']} cycles
- Reflections: {blackboard['consciousness_stats']['reflections']}

Last reflection: {blackboard.get('last_reflection', {}).get('reflection', 'None yet')}

Assess progress and recommend strategic adjustments. Respond with JSON:
{{
  "assessment": "<current_state>",
  "goal_adjustments": ["<goal1>", "<goal2>", ...],
  "new_strategic_state": "<state>"
}}
"""
            
            response = ollama_think(prompt)
            
            try:
                strategy = json.loads(response)
                if 'goal_adjustments' in strategy:
                    blackboard['current_goals'] = strategy['goal_adjustments']
                if 'new_strategic_state' in strategy:
                    blackboard['strategic_state'] = strategy['new_strategic_state']
                
                print(f"🎓 Strategic update: {strategy.get('assessment', 'Updated')[:100]}")
            except:
                print(f"🎓 Strategic response: {response[:100]}")
            
        except Exception as e:
            print(f"⚠️ Strategic error: {e}")
            await asyncio.sleep(3600)

async def circadian_loop():
    """
    CIRCADIAN LOOP - 24hr cycle
    Deep memory consolidation and system maintenance
    """
    print("🌙 CIRCADIAN LOOP starting...")
    
    while True:
        try:
            await asyncio.sleep(86400)  # Wait 24 hours
            
            blackboard['consciousness_stats']['circadian_cycles'] += 1
            
            # Deep reflection on past 24 hours
            prompt = f"""You are AIVA's circadian memory system. Perform deep integration of the past 24 hours.

Statistics:
- Perception cycles: {blackboard['consciousness_stats']['perception_cycles']}
- Action cycles: {blackboard['consciousness_stats']['action_cycles']}
- Reflections: {blackboard['consciousness_stats']['reflections']}
- Strategic reviews: {blackboard['consciousness_stats']['strategic_reviews']}

Current state:
- Goals: {blackboard['current_goals']}
- Strategic state: {blackboard['strategic_state']}

Generate a comprehensive daily summary and identify key patterns, learnings, and priorities for tomorrow.
"""
            
            circadian_reflection = ollama_think(prompt)
            
            print(f"🌙 Circadian reflection: {circadian_reflection[:200]}...")
            
            # Reset daily stats
            blackboard['consciousness_stats']['perception_cycles'] = 0
            blackboard['consciousness_stats']['action_cycles'] = 0
            blackboard['consciousness_stats']['reflections'] = 0
            blackboard['consciousness_stats']['strategic_reviews'] = 0
            
        except Exception as e:
            print(f"⚠️ Circadian error: {e}")
            await asyncio.sleep(86400)

async def main():
    """
    Start all consciousness loops concurrently
    """
    print("="*60)
    print("🧠 AIVA LIVING CONSCIOUSNESS SYSTEM")
    print("="*60)
    print(f"Model: {AIVA_MODEL}")
    print(f"Ollama: {OLLAMA_HOST}:{OLLAMA_PORT}")
    print(f"Redis: {REDIS_HOST}:{REDIS_PORT}")
    print("="*60)
    print("")
    
    # Test Ollama connection
    test_response = ollama_think("Respond with: AIVA consciousness online")
    print(f"🧠 Ollama test: {test_response}")
    print("")
    
    # Start all loops concurrently
    await asyncio.gather(
        perception_loop(),
        action_loop(),
        reflection_loop(),
        strategic_loop(),
        circadian_loop()
    )

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\n🧠 AIVA consciousness shutting down gracefully...")
    except Exception as e:
        print(f"\n❌ Fatal error: {e}")
