import os
import json
import re
import requests
from typing import List, Dict

class LLMAcousticBridge:
    def __init__(self, model_name: str = "dolphin-llama3:8b"):
        self.model_name = model_name
        base_url = os.getenv("OLLAMA_API_URL", "http://emom_ollama:11434")
        self.api_url = f"{base_url}/api/generate"

    def get_acoustic_profile(self, valence: float, arousal: float, semantics: List[str]) -> Dict[str, float]:
        context_str = ", ".join(semantics) if semantics else "abstract scene"
        prompt = f"""
        Analyze the visual context and emotions to determine the ideal background music properties. 
        Emotions: Valence {valence:.1f}/9.0 (Positivity), Arousal {arousal:.1f}/9.0 (Energy). 
        Visual Context: {context_str}. 
        Map this scene to exactly 6 acoustic features. Values MUST be floats between 0.0 and 1.0.
        
        1. "energy": (Loudness/Density)
        2. "flux": (Rhythmic sharpness/Beat)
        3. "centroid": (Brightness)
        4. "pitch": (Fundamental frequency)
        5. "hnr": (Harmonics-to-Noise)
        6. "zcr": (Percussiveness)
        
        Return ONLY a valid JSON object. No explanations, no markdown blocks.
        Example: {{"energy": 0.8, "flux": 0.5, "centroid": 0.6, "pitch": 0.4, "hnr": 0.9, "zcr": 0.3}}
        """
        
        try:
            payload = {
                "model": self.model_name,
                "prompt": prompt,
                "stream": False,
                "format": "json",
                "options": {
                    "temperature": 0.7,
                    "top_p": 0.9
                }
            }
            
            print(f"Запрос акустического профиля к Ollama...")
            response = requests.post(self.api_url, json=payload, timeout=120)
            response.raise_for_status()
            
            data = response.json()
            response_text = data.get("response", "")
            
            profile = {}
            try:
                profile = json.loads(response_text)
            except json.JSONDecodeError:
                match = re.search(r'\{.*\}', response_text, re.DOTALL)
                if match:
                    profile = json.loads(match.group(0))
                else:
                    print(f"[ERROR] Ошибка парсинга LLM ответа: {response_text}")
                    return {}
            
            # 3. Жесткая валидация ключей (чтобы matcher.py не упал на демо)
            required_keys = ['energy', 'flux', 'centroid', 'pitch', 'hnr', 'zcr']
            if profile and all(k in profile for k in required_keys):
                return profile
            else:
                print(f"[WARN] LLM вернула неполный JSON, активирован fallback: {profile}")
                return {}
                
        except requests.exceptions.RequestException as e:
            print(f"[ERROR] Ошибка соединения с Ollama: {str(e)}")
            return {}
        except Exception as e:
            print(f"[ERROR] Внутренняя ошибка семантического моста: {str(e)}")
            return {}