"""
OpenVoiceUI Integration Module
Connects the main SaaS platform with OpenVoiceUI instances
"""
import os
import subprocess
import logging
from typing import Dict, Optional
import docker
import requests

logger = logging.getLogger(__name__)


class OpenVoiceUIIntegration:
    """Handles integration with OpenVoiceUI"""

    def __init__(self, install_path: str = None):
        self.install_path = install_path or os.getenv(
            'OPENVOICEUI_INSTALL_PATH',
            '/home/ashraffarid2010/wakelai.com/voice_engine/core'
        )
        self.base_url = os.getenv('OPENVOICEUI_BASE_URL', 'http://localhost:5001')

    def is_installed(self) -> bool:
        """Check if OpenVoiceUI is installed"""
        return os.path.exists(self.install_path)

    def get_status(self) -> Dict:
        """Get OpenVoiceUI status"""
        try:
            response = requests.get(f"{self.base_url}/health", timeout=5)
            return {
                'installed': self.is_installed(),
                'running': response.status_code == 200,
                'version': self.get_version()
            }
        except Exception as e:
            return {
                'installed': self.is_installed(),
                'running': False,
                'error': str(e)
            }

    def get_version(self) -> Optional[str]:
        """Get OpenVoiceUI version"""
        try:
            package_json = os.path.join(self.install_path, 'package.json')
            if os.path.exists(package_json):
                with open(package_json) as f:
                    import json
                    data = json.load(f)
                    return data.get('version')
        except Exception as e:
            logger.error(f"Failed to get version: {e}")
        return None

    def start_instance(self, instance_id: str, port: int, config: Dict = None) -> bool:
        """Start a new OpenVoiceUI instance"""
        try:
            # Create instance directory
            instance_dir = os.path.join(
                os.path.dirname(self.install_path),
                'instances',
                instance_id
            )
            os.makedirs(instance_dir, exist_ok=True)

            # Create instance configuration
            env_file = os.path.join(instance_dir, '.env')
            with open(env_file, 'w') as f:
                f.write(f"""# Instance {instance_id} Configuration
INSTANCE_ID={instance_id}
PORT={port}
BASE_URL=http://localhost:{port}

# LLM Configuration
CLAWDBOT_AUTH_TOKEN={os.getenv('CLAWDBOT_AUTH_TOKEN')}
ANTHROPIC_API_KEY={os.getenv('ANTHROPIC_API_KEY')}

# TTS Configuration
TTS_PROVIDER={os.getenv('TTS_PROVIDER', 'supertonic')}
GROQ_API_KEY={os.getenv('GROQ_API_KEY')}
ELEVENLABS_API_KEY={os.getenv('ELEVENLABS_API_KEY')}

# STT Configuration
STT_PROVIDER={os.getenv('STT_PROVIDER', 'web_speech')}
DEEPGRAM_API_KEY={os.getenv('DEEPGRAM_API_KEY')}

# Features
ENABLE_3D_UI={config.get('enable_3d_ui', True) if config else True}
ENABLE_CANVAS={config.get('enable_canvas', True) if config else True}
""")

            # Start using Docker if available
            if self._start_with_docker(instance_id, instance_dir, port):
                logger.info(f"Started instance {instance_id} with Docker")
                return True

            # Fallback: Start with npm
            return self._start_with_npm(instance_id, instance_dir, port)

        except Exception as e:
            logger.error(f"Failed to start instance {instance_id}: {e}")
            return False

    def _start_with_docker(self, instance_id: str, instance_dir: str, port: int) -> bool:
        """Start instance using Docker"""
        try:
            client = docker.from_env()
            container_name = f"wakelai-{instance_id}"

            # Remove existing container if any
            try:
                existing = client.containers.get(container_name)
                existing.remove(force=True)
            except:
                pass

            # Run new container
            container = client.containers.run(
                image="openvoiceui:latest",
                name=container_name,
                detach=True,
                ports={5001: port},
                volumes={
                    instance_dir: {'bind': '/app/config', 'mode': 'rw'}
                },
                environment={
                    'INSTANCE_ID': instance_id,
                    'PORT': 5001
                },
                restart_policy={"Name": "unless-stopped"}
            )

            return True

        except Exception as e:
            logger.warning(f"Docker start failed: {e}")
            return False

    def _start_with_npm(self, instance_id: str, instance_dir: str, port: int) -> bool:
        """Start instance using npm"""
        try:
            # Start OpenVoiceUI with custom port
            env = os.environ.copy()
            env['PORT'] = str(port)
            env['INSTANCE_ID'] = instance_id

            subprocess.Popen(
                ['npx', 'openvoiceui', 'start'],
                cwd=instance_dir,
                env=env,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )

            return True

        except Exception as e:
            logger.error(f"npm start failed: {e}")
            return False

    def stop_instance(self, instance_id: str) -> bool:
        """Stop a running instance"""
        try:
            client = docker.from_env()
            container_name = f"wakelai-{instance_id}"

            try:
                container = client.containers.get(container_name)
                container.stop()
                return True
            except docker.errors.NotFound:
                logger.warning(f"Container {container_name} not found")
                return False

        except Exception as e:
            logger.error(f"Failed to stop instance {instance_id}: {e}")
            return False

    def get_instance_logs(self, instance_id: str, lines: int = 100) -> list:
        """Get logs from instance"""
        try:
            client = docker.from_env()
            container_name = f"wakelai-{instance_id}"

            try:
                container = client.containers.get(container_name)
                logs = container.logs(tail=lines).decode('utf-8')
                return logs.split('\n')
            except docker.errors.NotFound:
                return []

        except Exception as e:
            logger.error(f"Failed to get logs: {e}")
            return []


# Singleton instance
_integration = None


def get_openvoiceui_integration() -> OpenVoiceUIIntegration:
    """Get OpenVoiceUI integration singleton"""
    global _integration
    if _integration is None:
        _integration = OpenVoiceUIIntegration()
    return _integration
