"""Voice command parsing logic."""

from __future__ import annotations

import json
import os
import unicodedata
from typing import Dict


def normalize(text: str) -> str:
    """Normalize text: lowercase, remove accents."""
    text = text.lower().strip()
    text = unicodedata.normalize("NFKD", text)
    text = "".join([c for c in text if not unicodedata.combining(c)])
    return text


def rule_parse(transcript: str) -> Dict[str, str]:
    """Parse voice command using rule-based approach."""
    text = normalize(transcript)

    action = "error"
    if any(w in text for w in ["reiniciar", "reinicia", "reset"]):
        action = "reiniciar"
    elif any(w in text for w in ["sube", "subir", "arriba"]):
        action = "subir"
    elif any(w in text for w in ["baja", "bajar", "abajo"]):
        action = "bajar"
    elif any(w in text for w in ["soltar", "deja", "dejar"]):
        action = "soltar"
    elif any(w in text for w in ["tomar", "toma", "agarra", "agarrar", "coger", "chupar", "succionar"]):
        action = "tomar"
    elif any(w in text for w in ["ir", "ve", "mover", "muevete", "acercar"]):
        action = "ir"

    color = "no especificado"
    if "rojo" in text:
        color = "rojo"
    elif "azul" in text:
        color = "azul"
    elif "amarillo" in text:
        color = "amarillo"
    elif "blanco" in text:
        color = "blanco"

    obj = "no especificado"
    if "estrella" in text:
        obj = "estrella"
    elif "cilindro" in text:
        obj = "cilindro"
    elif "cubo" in text:
        obj = "cubo"
    elif "caja" in text:
        obj = "caja"

    size = "no especificado"
    if "grande" in text:
        size = "grande"
    elif "pequeno" in text or "pequeño" in text or "chico" in text:
        size = "pequeno"

    if action == "error":
        return {"resultado": "error"}
    return {
        "resultado": "ok",
        "accion": action,
        "objeto": obj,
        "color": color,
        "tamano": size,
    }


def build_gemini_prompt(transcript: str) -> str:
    """Build prompt for Gemini LLM parsing."""
    return f"""Interpreta el siguiente comando de voz de un niño, convertido a texto, para controlar
    un robot (manito). Asegúrate de responder con 'accion', 'objeto', 'color' y 'tamano'. Si el color
    o el tamaño no están especificados, responde con 'no especificado'. Si no entiendes la frase,
    responde con 'resultado: error'. En caso contrario, responde con 'resultado: ok'. Las acciones
    posibles son 'bajar', 'subir', 'soltar', 'tomar', 'ir', 'reiniciar'. Los colores posibles son 'rojo',
    'blanco','azul' y 'amarillo'. Los tamaños posibles son 'grande', 'pequeno'. Los posible objetos son estrella,
    cilindro, cubo y caja; cualquier otro objeto es error.
    Comando: "{transcript}"
    Nota: Los comandos pueden incluir variaciones en la expresión y errores comunes en el lenguaje de
    los niños. Normaliza la respuesta a las categorías establecidas. La salida es un json con los campos
    'resultado', 'accion', 'objeto', 'color' y 'tamano'. Adicionalmente los ninos pueden decir tomar,chupar, succionar o similar para tomar un objeto.
    """


def parse_command(transcript: str, llm_provider: str = "rules") -> Dict[str, str]:
    """Parse voice command using specified provider."""
    if llm_provider == "gemini":
        try:
            from google import genai
            from google.genai import types
        except Exception:
            return rule_parse(transcript)

        api_key = os.getenv("GOOGLE_API_KEY")
        if not api_key:
            return rule_parse(transcript)

        try:
            client = genai.Client(api_key=api_key)
            prompt = build_gemini_prompt(transcript)
            reply = client.models.generate_content(
                model=os.getenv("GEMINI_MODEL", "gemini-2.0-flash"),
                contents=prompt,
                config=types.GenerateContentConfig(temperature=0.5),
            )
            raw = str(reply.text).replace("```json", "").replace("```", "")
            return json.loads(raw)
        except json.JSONDecodeError:
            return {"resultado": "error"}
        except Exception:
            return rule_parse(transcript)
    else:
        return rule_parse(transcript)
