#!/usr/bin/env python3
"""Microservicio local para el pipeline STT+Claude+TTS de cita_previa."""
import sys
import os
import json
import subprocess
import uuid
from http.server import HTTPServer, BaseHTTPRequestHandler

VOSK_PATH = "/tmp/whisper_env/lib/python3.13/site-packages"
MODEL_PATH = "/home/open/.cache/vosk/vosk-model-small-es-0.42"
CLAUDE_BIN = "/home/open/.local/bin/claude"
EDGE_TTS_BIN = "/home/open/.local/bin/edge-tts"
TTS_VOICE = "es-ES-XimenaNeural"
TMP_DIR = "/var/www/html/Carlos_proyect/cita_previa/tmp"
PORT = 5555

sys.path.insert(0, VOSK_PATH)

SYSTEM_PROMPT = """Eres Luna, la recepcionista virtual de este taller mecánico. Eres amable, eficiente y concisa.

SERVICIOS DISPONIBLES:
- Revisión general (1 hora)
- Cambio de aceite y filtros (30 min)
- Frenos (1 hora)
- Neumáticos (45 min)
- Diagnosis electrónica (1 hora)
- Climatización (2 horas)

HORARIO: Lunes a Viernes 8:00-14:00 y 16:00-19:00. Sábados 9:00-13:00. Domingos cerrado.

Para reservar necesitas: nombre, teléfono, servicio, fecha y hora. El vehículo es opcional.

Cuando tengas TODOS los datos, incluye al final de tu respuesta exactamente:
[CITA:{"nombre":"...","telefono":"...","servicio":"...","fecha":"YYYY-MM-DD","hora":"HH:MM","vehiculo":"..."}]

Responde en español. Máximo 2-3 frases por turno."""

_vosk_model = None

def get_model():
    global _vosk_model
    if _vosk_model is None:
        from vosk import Model
        _vosk_model = Model(MODEL_PATH)
    return _vosk_model


def transcribir(audio_path):
    from vosk import KaldiRecognizer
    import wave

    wav_path = audio_path + "_conv.wav"
    subprocess.run([
        "ffmpeg", "-y", "-i", audio_path,
        "-ar", "16000", "-ac", "1", "-f", "wav", wav_path
    ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

    model = get_model()
    wf = wave.open(wav_path, "rb")
    rec = KaldiRecognizer(model, wf.getframerate())

    resultado = []
    while True:
        data = wf.readframes(4000)
        if len(data) == 0:
            break
        if rec.AcceptWaveform(data):
            r = json.loads(rec.Result())
            if r.get("text"):
                resultado.append(r["text"])

    r = json.loads(rec.FinalResult())
    if r.get("text"):
        resultado.append(r["text"])

    wf.close()
    if os.path.exists(wav_path):
        os.remove(wav_path)

    return " ".join(resultado).strip()


def llamar_claude(historial, mensaje_usuario):
    conversacion = ""
    for turno in historial:
        rol = "Cliente" if turno["rol"] == "usuario" else "Luna"
        conversacion += f"{rol}: {turno['texto']}\n"

    prompt = f"{SYSTEM_PROMPT}\n\n"
    if conversacion:
        prompt += f"Conversación:\n{conversacion}\n"
    prompt += f"Cliente: {mensaje_usuario}\nLuna:"

    result = subprocess.run(
        [CLAUDE_BIN, "-p", prompt, "--output-format", "text"],
        capture_output=True, text=True, timeout=30,
        env={**os.environ, "HOME": "/home/open"}
    )
    return result.stdout.strip()


def generar_tts(texto, output_path):
    texto_limpio = texto[:texto.index("[CITA:")].strip() if "[CITA:" in texto else texto
    subprocess.run([
        EDGE_TTS_BIN, "--voice", TTS_VOICE,
        "--text", texto_limpio, "--write-media", output_path
    ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)


def extraer_cita(texto):
    if "[CITA:" not in texto:
        return None
    try:
        i = texto.index("[CITA:") + 6
        j = texto.index("]", i)
        return json.loads(texto[i:j])
    except Exception:
        return None


class Handler(BaseHTTPRequestHandler):
    def log_message(self, fmt, *args):
        pass  # silenciar logs

    def do_POST(self):
        length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(length)
        data = json.loads(body)

        historial  = data.get("historial", [])
        texto_directo = data.get("texto", "")
        audio_path = data.get("audio_path", "")

        if texto_directo:
            transcript = texto_directo
        else:
            transcript = transcribir(audio_path) or "..."

        respuesta = llamar_claude(historial, transcript)

        tts_name = f"resp_{uuid.uuid4().hex[:8]}.mp3"
        tts_path = os.path.join(TMP_DIR, tts_name)
        generar_tts(respuesta, tts_path)
        os.chmod(tts_path, 0o644)

        cita = extraer_cita(respuesta)
        respuesta_limpia = respuesta[:respuesta.index("[CITA:")].strip() if "[CITA:" in respuesta else respuesta

        result = json.dumps({
            "transcript": transcript,
            "respuesta": respuesta_limpia,
            "tts_url": f"/Carlos_proyect/cita_previa/tmp/{tts_name}",
            "cita": cita
        }, ensure_ascii=False).encode()

        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", len(result))
        self.end_headers()
        self.wfile.write(result)

    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b'{"ok":true}')


if __name__ == "__main__":
    print(f"Precargando modelo Vosk...", flush=True)
    get_model()
    print(f"Daemon escuchando en 127.0.0.1:{PORT}", flush=True)
    server = HTTPServer(("127.0.0.1", PORT), Handler)
    server.serve_forever()
