import logging
import os
from typing import List, Dict, Optional
from fastapi import HTTPException
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from core import StudentNationality, Models
from services.pgvector_service import PGVectorService
from services.openai_service import OpenAIService
from services.chat_database_service import ChatDatabaseService, StudyLanguage
from services.pedagogy_service import PedagogyService
from services.connection_pool import ConnectionPool
from services.agent_helpers.query_handlers import QueryHandler
from services.agent_helpers.context_generator import ContextGenerator
from services.agent_helpers.response_generator import ResponseGenerator
from services.tts.tts_manager import get_tts_service

logger = logging.getLogger(__name__)

class AgentService:
    """Main service class for handling AI agent conversations with modular architecture"""

    def __init__(self, use_pgvector: bool = True, pool_handler: Optional[ConnectionPool] = None):
        # Initialize core services
        self.openai_service = OpenAIService()
        if not self.openai_service.is_available():
            logger.warning("Warning: OPENAI_API_KEY not found. Agent service will be disabled.")
        
        self.tts_service = get_tts_service(self.openai_service)
        if not self.tts_service.is_available():
            logger.warning("Warning: No TTS service is available.")

        # Database setup
        self.pool_handler = pool_handler
        if self.pool_handler is None:
            self.pool_handler = ConnectionPool(
                minconn=1,
                maxconn=20,
                dbname=os.getenv("DB_NAME"),
                user=os.getenv("DB_USER"),
                password=os.getenv("DB_PASSWORD"),
                host=os.getenv("DB_HOST"),
                port=os.getenv("DB_PORT")
            )
        
        self.db_service = ChatDatabaseService(self.pool_handler)
        
        # PGVector setup
        self.use_pgvector = use_pgvector
        if self.use_pgvector:
            self.pgvector = PGVectorService(self.pool_handler)
            self.pgvector.setup_curriculum_table()
        else:
            self.pgvector = None

        self.pedagogy_service = PedagogyService()
        
        # Initialize modular components
        self.query_handler = QueryHandler(self.openai_service, self.pgvector, self.db_service)
        self.context_generator = ContextGenerator(self.openai_service, self.pgvector)
        self.response_generator = ResponseGenerator(
            self.openai_service, self.db_service, self.pedagogy_service,
            self.query_handler, self.context_generator
        )

    def is_available(self) -> bool:
        return self.openai_service.is_available()

    def text_to_speech(self, text: str, language: str) -> bytes:
        if not self.tts_service or not self.tts_service.is_available():
            raise HTTPException(status_code=503, detail="TTS service is not available")
        return self.tts_service.generate_speech(text, language)

    def generate_response(self, user_message: str, student_id: str, subject: str = "Science", 
                         model: str = Models.chat, temperature: float = 0.3, top_k: int = 3) -> str:
        """Main response generation method"""
        return self.response_generator.generate_response(
            user_message, student_id, subject, model, temperature, top_k
        )

    def search_similar(self, query_embedding: List[float], student_id: str, 
                      subject: str = "chemistry", top_k: int = 3):
        """Search similar content with student-specific filtering"""
        if not self.pgvector:
            raise HTTPException(status_code=400, detail="PGVector service not enabled")
        
        try:
            student_info = self.db_service.get_student_info(student_id)
            if not student_info:
                raise HTTPException(status_code=404, detail=f"Student with ID {student_id} not found")
            
            return self.pgvector.search_with_curriculum_context(
                query_embedding=query_embedding,
                grade=student_info['grade'],
                subject=subject,
                is_arabic=student_info['is_arabic'],
                limit=top_k
            )
        except Exception as e:
            logger.error(f"Error in search_similar: {e}")
            raise HTTPException(status_code=500, detail=f"Search failed: {str(e)}")

    def get_available_subjects(self, student_id: str) -> List[str]:
        """Get available subjects for the student"""
        if not self.pgvector:
            return []
        
        try:
            student_info = self.db_service.get_student_info(student_id)
            if not student_info:
                return []
            
            return self.pgvector.get_subjects_by_grade_and_language(
                student_info['grade'], student_info['is_arabic']
            )
        except Exception as e:
            logger.error(f"Error getting available subjects: {e}")
            return []

    def get_curriculum_overview(self, student_id: str, subject: str = "Science") -> Dict:
        """Get curriculum overview for a specific student"""
        if not self.pgvector:
            return {"error": "PGVector service not available"}
            
        try:
            student_info = self.db_service.get_student_info(student_id)
            if not student_info:
                return {"error": "Student not found"}
            
            curriculum = self.pgvector.get_curriculum_structure(
                student_info['grade'], student_info['is_arabic'], subject
            )
            
            if not curriculum:
                return {"error": f"No curriculum found for Grade {student_info['grade']}"}
            
            return {
                "student_info": {
                    "name": student_info['student_name'],
                    "grade": student_info['grade'],
                    "study_language": student_info['study_language'].value,
                    "nationality": student_info['nationality']
                },
                "curriculum": curriculum,
                "available_units": self.pgvector.get_units_for_grade(
                    student_info['grade'], student_info['is_arabic'], subject
                ),
                "source": "JSON-based curriculum structure"
            }
            
        except Exception as e:
            logger.error(f"Error getting curriculum overview: {e}")
            return {"error": str(e)}

    # Conversation management methods
    def export_conversation(self, student_id: str) -> List[Dict[str, str]]:
        """Export conversation history for a student"""
        return self.response_generator.get_conversation_history(student_id)

    def clear_conversation(self, student_id: str) -> Dict[str, str]:
        """Clear conversation history for a student"""
        try:
            self.db_service.clear_history(student_id)
            return {"status": "success", "message": f"Conversation cleared for student {student_id}"}
        except Exception as e:
            logger.error(f"Error clearing conversation: {e}")
            return {"status": "error", "message": f"Failed to clear conversation: {str(e)}"}

    def get_agent_stats(self, student_id: str) -> Dict:
        """Get conversation statistics for a student"""
        try:
            history = self.response_generator.get_conversation_history(student_id)
            user_messages = [msg for msg in history if msg['role'] == 'user']
            assistant_messages = [msg for msg in history if msg['role'] == 'assistant']
            system_messages = [msg for msg in history if msg['role'] == 'system']
            
            student_info = self.db_service.get_student_info(student_id)
            language_info = {}
            curriculum_info = {}
            
            if student_info:
                language_info = {
                    "study_language": student_info['study_language'].value,
                    "nationality": student_info['nationality'],
                    "grade": student_info['grade']
                }
                
                if self.pgvector:
                    curriculum = self.pgvector.get_curriculum_structure(
                        student_info['grade'], student_info['is_arabic']
                    )
                    curriculum_info = {
                        "curriculum_available": curriculum is not None,
                        "curriculum_source": "JSON file" if curriculum else "None",
                        "available_subjects": self.pgvector.get_subjects_by_grade_and_language(
                            student_info['grade'], student_info['is_arabic']
                        ),
                        "available_units": len(curriculum.get('units', [])) if curriculum else 0
                    }
            
            return {
                "student_id": student_id,
                "total_messages": len(history),
                "user_messages": len(user_messages),
                "assistant_messages": len(assistant_messages),
                "system_messages": len(system_messages),
                "conversation_active": len(history) > 0,
                **language_info,
                **curriculum_info
            }
        except Exception as e:
            logger.error(f"Error getting agent stats: {e}")
            return {"student_id": student_id, "error": str(e)}

    def get_curriculum_structure_info(self, student_id: str, subject: str = "Science") -> Dict:
        """Get detailed curriculum structure information"""
        if not self.pgvector:
            return {"error": "PGVector service not available"}
            
        try:
            student_info = self.db_service.get_student_info(student_id)
            if not student_info:
                return {"error": "Student not found"}
            
            curriculum = self.pgvector.get_curriculum_structure(
                student_info['grade'], student_info['is_arabic'], subject
            )
            
            if not curriculum:
                return {"error": "No curriculum structure found"}
            
            # Extract detailed structure info
            units_info = []
            if 'units' in curriculum:
                for unit in curriculum['units']:
                    unit_info = {
                        "number": unit.get('number'),
                        "name": unit.get('name'),
                        "description": unit.get('description', ''),
                        "concepts_count": len(unit.get('concepts', [])),
                        "concepts": []
                    }
                    
                    for concept in unit.get('concepts', []):
                        concept_info = {
                            "number": concept.get('number'),
                            "name": concept.get('name'),
                            "description": concept.get('description', ''),
                            "lessons_count": len(concept.get('lessons', []))
                        }
                        unit_info["concepts"].append(concept_info)
                    
                    units_info.append(unit_info)
            
            return {
                "student_info": {
                    "grade": student_info['grade'],
                    "language": "Arabic" if student_info['is_arabic'] else "English",
                    "nationality": student_info['nationality']
                },
                "curriculum_title": curriculum.get('title', ''),
                "total_units": len(units_info),
                "units": units_info,
                "source": "JSON-based curriculum file"
            }
            
        except Exception as e:
            logger.error(f"Error getting curriculum structure info: {e}")
            return {"error": str(e)}

    def close(self):
        """Close database connection pools"""
        if self.pool_handler:
            try:
                self.pool_handler.close_all()
            except Exception as e:
                logger.error(f"Error closing connection pools: {e}")

    def __del__(self):
        """Destructor to ensure connection pools are closed"""
        self.close()