# services/chat_service.py

from fastapi import UploadFile, HTTPException
from typing import Optional, Dict
import sys
import os
import time
import io
import random
import json

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from core import MessageType, AppConfig
from repositories import StorageRepository
from services.response_manager import ResponseManager
from services.openai_service import OpenAIService
from services.agent_service import AgentService
from services.segmentation_service import LanguageSegmentationService

class ChatService:
    def __init__(self, storage_repo: StorageRepository, response_manager: ResponseManager, 
                 config: AppConfig, openai_service: OpenAIService, agent_service: AgentService, segmentation_service: LanguageSegmentationService):
        from handlers import AudioMessageHandler, TextMessageHandler
        
        self.storage_repo = storage_repo
        self.response_manager = response_manager
        self.config = config
        self.openai_service = openai_service
        self.agent_service = agent_service
        self.segmentation_service = segmentation_service
        
        self.handlers = {
            MessageType.AUDIO: AudioMessageHandler(storage_repo, config.minio_bucket, openai_service),
            MessageType.TEXT: TextMessageHandler()
        }

    def _format_mcq_for_tts(self, mcq_data: Dict, is_arabic: bool) -> str:
        """ Formats a structured MCQ dictionary into a natural, speakable string for TTS. """
        question_text = mcq_data.get("question_text", "")
        options = [
            mcq_data.get("correct_answer"), mcq_data.get("wrong_answer_1"),
            mcq_data.get("wrong_answer_2"), mcq_data.get("wrong_answer_3")
        ]
        valid_options = [opt for opt in options if opt]
        random.shuffle(valid_options)
        spoken_text = f"{question_text}\n\n"
        spoken_text += "والاختيارات هي:\n" if is_arabic else "The options are:\n"
        for option in valid_options:
            spoken_text += f"{option}, \n"
        return spoken_text.strip()

# In chat_service.py
# REPLACE the entire process_message method with this one.

    def process_message(self, student_id: str, file: Optional[UploadFile] = None, text: Optional[str] = None, game_context: Optional[str] = None):
        """
        Processes a message, stores the full response in Redis, and returns a
        detailed confirmation payload that differs for text vs. MCQ responses.
        """
        try:
            if file and file.filename:
                user_message = self.handlers[MessageType.AUDIO].openai_service.transcribe_audio(file.file.read(), file.filename)
            elif text:
                user_message = text
            else:
                raise HTTPException(status_code=400, detail="No text or audio file provided.")

            final_message_for_agent = f"game context: {game_context}\nuser query: {user_message}" if game_context else user_message
            
            agent_response = self.agent_service.generate_response(
                user_message=final_message_for_agent,
                student_id=student_id,
            )

            response_payload_for_redis = None
            text_for_audio = ""
            agent_response_for_confirmation = ""

            # This block determines what to store in Redis and what text to generate audio from.
            # The logic here remains the same.
            if isinstance(agent_response, dict) and agent_response.get("type") == "mcq":
                mcq_data = agent_response.get("data")
                response_payload_for_redis = mcq_data
                student_info = self.agent_service.db_service.get_student_info(student_id)
                is_arabic = student_info.get('is_arabic', True) if student_info else True
                text_for_audio = self._format_mcq_for_tts(mcq_data, is_arabic)
                agent_response_for_confirmation = text_for_audio
            else:
                agent_response_text = str(agent_response)
                response_payload_for_redis = agent_response_text
                text_for_audio = agent_response_text
                agent_response_for_confirmation = agent_response_text

            # Generate audio for the prepared text
            audio_data = self._generate_and_upload_audio(text_for_audio, student_id)
            
            # Store the full payload (dict or string) and audio bytes in Redis for the polling endpoint
            self.response_manager.store_response(
                student_id=student_id,
                text=response_payload_for_redis,
                audio_filepath=audio_data.get("filepath"),
                audio_bytes=audio_data.get("bytes")
            )
            
            
            # Case 1: The response was an MCQ. Return the special structure.
            if isinstance(agent_response, dict) and agent_response.get("type") == "mcq":
                return {
                    "status": "success",
                    "message": "Message processed and MCQ response ready",
                    "student_id": student_id,
                    "response_type": "mcq",
                    "agent_response": agent_response_for_confirmation, # The speakable version
                    "question": agent_response.get("data"), # The NEW structured data field
                    "audio_filepath": audio_data.get("filepath")
                }
            
            # Case 2: The response was normal text. Return the standard structure.
            else:
                return {
                    "status": "success",
                    "message": "Message processed and agent response ready",
                    "student_id": student_id,
                    "response_type": "text",
                    "agent_response": agent_response_for_confirmation,
                    "audio_filepath": audio_data.get("filepath")
                }
            
        except Exception as e:
            print(f"Error processing message for student {student_id}: {e}")
            raise HTTPException(status_code=500, detail=f"Failed to process message: {str(e)}")
        
    def _generate_and_upload_audio(self, text: str, student_id: str) -> dict:
        """ Segments text, generates TTS audio, and uploads to MinIO. """
        try:
            segments = self.segmentation_service.segment_text(text)
            audio_bytes = self.agent_service.tts_service.generate_speech_from_sequence(segments)
            timestamp = int(time.time())
            filename = f"agent_response_{timestamp}_{student_id}.wav"
            minio_file_path = f"audio/{filename}"
            self.storage_repo.upload_file(io.BytesIO(audio_bytes), self.config.minio_bucket, minio_file_path)
            full_url = self.storage_repo.get_file_url(self.config.minio_bucket, minio_file_path, expires=3600)
            print(f"Successfully generated and uploaded TTS audio: {filename}")
            return {"bytes": audio_bytes, "filepath": full_url}
        except Exception as e:
            print(f"Error in _generate_and_upload_audio: {e}")
            return {"bytes": None, "filepath": None}