# --- START OF FILE routes.py ---

import aiohttp
from aiohttp import web
import logging
from sqlalchemy import desc 
from sqlalchemy.future import select
from sqlalchemy.exc import IntegrityError
from datetime import datetime
from database import async_session, Agent, CallSession, CallStatus
import os
import ffmpeg

logger = logging.getLogger("server")
RECORDINGS_DIR = "recordings"
# === РОУТЫ ДЛЯ ФРОНТЕНДА (Публичные) ===

async def list_agents(request):
    # ... код не изменился
    async with async_session() as session:
        result = await session.execute(select(Agent))
        agents = result.scalars().all()
        response_data = {}
        for agent in agents:
            response_data[agent.name] = {
                "id": agent.id, "name": agent.name, "model": agent.model, "voice": agent.voice,
                "instructions": agent.instructions, "turn_detection": agent.turn_detection_settings
            }
        return web.json_response(response_data)

async def create_session(request):
    """Проксирует запрос к OpenAI для получения ephemeral key. НЕ СОХРАНЯЕТ СЕССИЮ В БД."""
    try:
        agent_key = request.query.get("agent", "default")
        async with async_session() as session:
            result = await session.execute(select(Agent).where(Agent.name == agent_key))
            agent = result.scalar_one_or_none()
        if not agent: return web.json_response({"error": "Agent not found"}, status=404)
        
        OPENAI_API_KEY = request.app["OPENAI_API_KEY"]
        url = "https://api.openai.com/v1/realtime/sessions"
        headers = {"Authorization": f"Bearer {OPENAI_API_KEY}", "Content-Type": "application/json"}
        body = {
            "model": agent.model, "voice": agent.voice,
            "instructions": agent.instructions, "turn_detection": agent.turn_detection_settings,
            "input_audio_transcription": {"model": "whisper-1"}
        }
        
        async with aiohttp.ClientSession() as http_session:
            async with http_session.post(url, headers=headers, json=body) as resp:
                result = await resp.json()
                if resp.status >= 400:
                    logger.error(f"Ошибка OpenAI API при создании сессии: {result}")
                    return web.json_response(result, status=resp.status)
                
                # Просто возвращаем ответ от OpenAI. ID сессии здесь еще нет.
                logger.info(f"Для агента {agent_key} выдан ephemeral key.")
                return web.json_response(result)

    except Exception as e:
        logger.exception("Ошибка при проксировании запроса на создание сессии")
        return web.json_response({"error": str(e)}, status=500)

# === РОУТЫ ДЛЯ УПРАВЛЕНИЯ (Защищенные через Middleware) ===

async def create_agent(request):
    try:
        data = await request.json()
        new_agent = Agent(
            name=data["name"], model=data.get("model", "gpt-4o-realtime-preview"),
            voice=data["voice"], instructions=data["instructions"],
            turn_detection_settings=data["turn_detection"]
        )
        async with async_session() as session:
            session.add(new_agent)
            await session.commit()
        logger.info(f"АДМИН: Создан новый агент '{data['name']}'")
        return web.json_response({"status": "created", "name": data["name"]}, status=201)
    except IntegrityError: return web.json_response({"error": f"Agent with name '{data['name']}' already exists"}, status=409)
    except Exception as e:
        logger.exception("Ошибка при создании агента")
        return web.json_response({"error": str(e)}, status=400)

async def update_agent(request):
    """PUT /api/agents/{name} - Обновить агента"""
    agent_name = request.match_info['name']
    try:
        data = await request.json()
        async with async_session() as session:
            result = await session.execute(select(Agent).where(Agent.name == agent_name))
            agent = result.scalar_one_or_none()
            if not agent: return web.json_response({"error": "Agent not found"}, status=404)
            
            # Обновляем поля, если они есть в запросе
            agent.model = data.get("model", agent.model)
            agent.voice = data.get("voice", agent.voice)
            agent.instructions = data.get("instructions", agent.instructions)
            agent.turn_detection_settings = data.get("turn_detection", agent.turn_detection_settings)
            
            await session.commit()
            logger.info(f"АДМИН: Обновлен агент '{agent_name}'")
            return web.json_response({"status": "updated", "name": agent_name})
    except Exception as e:
        logger.exception(f"Ошибка при обновлении агента {agent_name}")
        return web.json_response({"error": str(e)}, status=400)

async def delete_agent(request):
    agent_name = request.match_info['name']
    if agent_name in ["default", "sales"]:
         return web.json_response({"error": "Cannot delete default agents"}, status=400)

    async with async_session() as session:
        result = await session.execute(select(Agent).where(Agent.name == agent_name))
        agent = result.scalar_one_or_none()
        if agent:
            await session.delete(agent)
            await session.commit()
            logger.info(f"АДМИН: Удален агент '{agent_name}'")
            return web.json_response({"status": "deleted", "name": agent_name})
        else:
            return web.json_response({"error": "Agent not found"}, status=404)

async def save_transcript(request):
    """Находит сессию по ID, обновляет ее. Если не находит - создает новую."""
    try:
        session_id = request.match_info['session_id']
        data = await request.json()
        transcript_text = data.get("transcript")
        agent_name = data.get("agent_name") # Фронтенд теперь должен присылать имя агента

        if not agent_name:
            return web.json_response({"error": "agent_name is required"}, status=400)

        async with async_session() as session:
            # Пытаемся найти существующую запись
            result = await session.execute(
                select(CallSession).where(CallSession.session_id_openai == session_id)
            )
            call_session = result.scalar_one_or_none()

            if not call_session:
                # Если записи нет - создаем ее
                logger.info(f"Сессия [{session_id}] не найдена, создаем новую запись.")
                call_session = CallSession(
                    session_id_openai=session_id,
                    agent_name=agent_name,
                    start_time=datetime.utcnow() # Примечание: время старта будет примерным
                )
                session.add(call_session)
            
            # Обновляем поля
            call_session.end_time = datetime.utcnow()
            call_session.status = CallStatus.COMPLETED
            call_session.transcript = transcript_text
            
            await session.commit()
            
            duration = (call_session.end_time - call_session.start_time).total_seconds()
            logger.info(f"Сохранена транскрипция для сессии [{session_id}]. Длительность: ~{duration:.2f} сек.")
            return web.json_response({"status": "success"})

    except Exception as e:
        logger.exception(f"Ошибка при сохранении транскрипции")
        return web.json_response({"error": str(e)}, status=500)

async def list_sessions(request):
    """Возвращает 5 последних завершенных сессий."""
    try:
        async with async_session() as session:
            # Выбираем сессии, сортируем по времени начала (новые сначала) и берем первые 5
            result = await session.execute(
                select(CallSession)
                .where(CallSession.status == CallStatus.COMPLETED)
                .order_by(desc(CallSession.start_time))
                .limit(5)
            )
            sessions = result.scalars().all()
            
            # Формируем красивый JSON для ответа
            response_data = []
            for s in sessions:
                duration = (s.end_time - s.start_time).total_seconds() if s.end_time else 0
                response_data.append({
                    "id": s.id,
                    "agent_name": s.agent_name,
                    "start_time": s.start_time.isoformat(),
                    "duration_seconds": round(duration),
                    "transcript": s.transcript
                })
            
            return web.json_response(response_data)
    except Exception as e:
        logger.exception("Ошибка при получении списка сессий")
        return web.json_response({"error": str(e)}, status=500)


async def upload_audio_recordings(request):
    """Принимает два аудиофайла, объединяет их в один и сохраняет."""
    session_id = request.match_info['session_id']
    reader = await request.multipart()
    
    temp_user_path = None
    temp_ai_path = None
    agent_name = "unknown_agent" # Имя по умолчанию

    try:
        # 1. Сохраняем входящие файлы во временные
        async for field in reader:
            # Сначала ищем поле с именем агента, которое мы будем использовать в имени файла
            if field.name == 'agent_name':
                agent_name_bytes = await field.read()
                agent_name = agent_name_bytes.decode('utf-8')

            if field.name in ('user_audio', 'ai_audio'):
                temp_filename = f"temp_{session_id}_{field.name}.webm"
                temp_filepath = os.path.join(RECORDINGS_DIR, temp_filename)
                
                with open(temp_filepath, 'wb') as f:
                    while True:
                        chunk = await field.read_chunk()
                        if not chunk: break
                        f.write(chunk)
                
                if field.name == 'user_audio':
                    temp_user_path = temp_filepath
                else:
                    temp_ai_path = temp_filepath

        if not temp_user_path or not temp_ai_path:
            return web.json_response({"error": "Both user_audio and ai_audio files are required"}, status=400)

        # 2. Объединяем файлы с помощью FFmpeg, используя новое имя
        # Форматируем текущее время в строку "ДД-ММ_ЧЧ-ММ"
        timestamp = datetime.now().strftime("%d-%m_%H-%M")
        output_filename = f"{agent_name}_{timestamp}.mp3"
        output_path = os.path.join(RECORDINGS_DIR, output_filename)

        input_user = ffmpeg.input(temp_user_path)
        input_ai = ffmpeg.input(temp_ai_path)

        merged = ffmpeg.filter([input_user, input_ai], 'amerge', inputs=2)
        ffmpeg.output(merged, output_path, ac=2).run(overwrite_output=True)

        logger.info(f"Аудиофайлы объединены и сохранены: {output_path}")

        # 3. Обновляем запись в БД
        async with async_session() as session:
            result = await session.execute(select(CallSession).where(CallSession.session_id_openai == session_id))
            call_session = result.scalar_one_or_none()
            if call_session:
                call_session.combined_audio_path = output_path
                await session.commit()
                logger.info(f"Путь к объединенному аудио для сессии [{session_id}] обновлен.")
                return web.json_response({"status": "audio_merged_and_saved"})
            else:
                logger.warning(f"Попытка сохранить аудио для несуществующей сессии: {session_id}")
                return web.json_response({"error": "Session not found"}, status=404)

    except Exception as e:
        logger.exception("Ошибка при обработке и объединении аудио")
        return web.json_response({"error": str(e)}, status=500)
    finally:
        # 4. Удаляем временные файлы
        if temp_user_path and os.path.exists(temp_user_path):
            os.remove(temp_user_path)
        if temp_ai_path and os.path.exists(temp_ai_path):
            os.remove(temp_ai_path)

async def proxy_realtime_request(request):
    """
    Принимает SDP-offer от клиента и ephemeral_key,
    проксирует запрос в OpenAI и возвращает их ответ.
    """
    try:
        ephemeral_key = request.headers.get('Authorization', '').replace('Bearer ', '')
        if not ephemeral_key:
            return web.json_response({"error": "Authorization header with ephemeral key is required"}, status=400)

        offer_sdp = await request.text()

        url = "https://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview"
        headers = {
            "Authorization": f"Bearer {ephemeral_key}",
            "Content-Type": "application/sdp"
        }

        async with aiohttp.ClientSession() as http_session:
            async with http_session.post(url, headers=headers, data=offer_sdp) as resp:
                if resp.status >= 400:
                    error_text = await resp.text()
                    logger.error(f"Ошибка проксирования в OpenAI Realtime API: {resp.status} - {error_text}")
                    return web.Response(text=error_text, status=resp.status, content_type=resp.content_type)
                
                answer_sdp = await resp.text()
                return web.Response(text=answer_sdp, status=200, content_type="application/sdp")

    except Exception as e:
        logger.exception("Критическая ошибка в прокси-хэндлере")
        return web.json_response({"error": str(e)}, status=500)


# --- Регистрация всех роутов ---
def setup_routes(app):
    # Публичные роуты
    app.router.add_get("/api/agents", list_agents)
    app.router.add_get("/api/session", create_session)
    app.router.add_post("/api/sessions/{session_id}/transcript", save_transcript)
    app.router.add_get("/api/sessions", list_sessions)
    app.router.add_post("/api/sessions/{session_id}/recordings", upload_audio_recordings)
    app.router.add_post("/api/realtime", proxy_realtime_request)
    # Админские роуты
    app.router.add_post("/api/agents", create_agent)
    app.router.add_put("/api/agents/{name}", update_agent) # <-- Новый роут
    app.router.add_delete("/api/agents/{name}", delete_agent)
    logger.info("Роуты API настроены.")

# --- END OF FILE routes.py ---