"""
60db API Client
"""

import requests
from typing import Optional, Dict, Any, List, Callable
import json
import base64


class SixtyDBClient:
    """Official 60db API client"""
    
    def __init__(self, api_key: str, base_url: str = "https://api-dev.qcall.ai/tts"):
        """
        Initialize the 60db client
        
        Args:
            api_key: Your 60db API key
            base_url: API base URL (default: https://api-dev.qcall.ai/tts)
        """
        self.api_key = api_key
        self.base_url = base_url.rstrip('/')
        self.session = requests.Session()
        self.session.headers.update({
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        })
    
    def _request(self, method: str, endpoint: str, **kwargs) -> Any:
        """Make HTTP request"""
        url = f"{self.base_url}{endpoint}"
        response = self.session.request(method, url, **kwargs)
        response.raise_for_status()
        
        if kwargs.get('stream'):
            return response
        
        content_type = response.headers.get('content-type', '')
        if 'application/json' in content_type:
            return response.json()
        return response.content
    
    # TTS Methods
    def text_to_speech(self, text: str, voice_id: Optional[str] = None, enhance: Optional[bool] = True, speed: Optional[float] = 1.0, **params) -> bytes:
        """
        Convert text to speech
        
        Args:
            text: Text to convert
            voice_id: Voice ID to use
            enhance: Enable audio enhancement
            speed: Speech speed (0.5 to 2.0)
            **params: Additional parameters
            
        Returns:
            Audio data as bytes
        """
        data = {'text': text, 'enhance': enhance, 'speed': speed, **params}
        if voice_id:
            data['voice_id'] = voice_id
        
        response = self._request('POST', '/tts-stream', json=data)
        
        # Handle JSON response with base64 audio
        if isinstance(response, dict) and response.get('success') and response.get('audio_base64'):
            return base64.b64decode(response['audio_base64'])
        
        # Fallback for binary response
        if isinstance(response, bytes):
            return response
            
        raise Exception(response.get('message', 'Failed to generate audio'))
    
    def text_to_speech_stream(
        self,
        text: str,
        on_chunk: Callable[[bytes], None],
        voice_id: Optional[str] = None,
        on_complete: Optional[Callable[[], None]] = None,
        on_error: Optional[Callable[[str], None]] = None,
        **params
    ) -> None:
        """
        Stream text to speech with callbacks
        
        Args:
            text: Text to convert
            on_chunk: Callback for audio chunks
            voice_id: Voice ID to use
            on_complete: Callback when complete
            on_error: Callback for errors
            **params: Additional parameters
        """
        data = {'text': text, **params}
        if voice_id:
            data['voice_id'] = voice_id
        
        try:
            response = requests.post(
                f"{self.base_url}/tts-stream",
                headers={'Authorization': f'Bearer {self.api_key}', 'Content-Type': 'application/json'},
                json=data,
                stream=True
            )
            response.raise_for_status()
            
            buffer = ""
            for chunk in response.iter_content(chunk_size=None, decode_unicode=True):
                if chunk:
                    buffer += chunk
                    lines = buffer.split('\n')
                    buffer = lines.pop()
                    
                    for line in lines:
                        if not line.strip():
                            continue
                        try:
                            parsed = json.loads(line)
                            if parsed.get('type') == 'error':
                                if on_error:
                                    on_error(parsed.get('message', 'Unknown error'))
                            elif 'result' in parsed and 'audioContent' in parsed['result']:
                                audio_bytes = base64.b64decode(parsed['result']['audioContent'])
                                on_chunk(audio_bytes)
                        except json.JSONDecodeError:
                            pass
            
            if on_complete:
                on_complete()
        except Exception as e:
            if on_error:
                on_error(str(e))
            raise
    
    # STT Methods
    def speech_to_text(self, audio_file, language: Optional[str] = None) -> Dict[str, Any]:
        """
        Transcribe audio to text
        
        Args:
            audio_file: Audio file path or file object
            language: Language code
            
        Returns:
            Transcription result
        """
        files = {'audio': audio_file}
        data = {}
        if language:
            data['language'] = language
        
        headers = {'Authorization': f'Bearer {self.api_key}'}
        response = requests.post(
            f"{self.base_url}/stt",
            headers=headers,
            files=files,
            data=data
        )
        response.raise_for_status()
        return response.json()
    
    def get_languages(self) -> List[Dict[str, Any]]:
        """Get supported languages"""
        return self._request('GET', '/stt/languages')
    
    # Voice Methods
    def get_voices(self) -> List[Dict[str, Any]]:
        """Get all voices"""
        return self._request('GET', '/voices')
    
    def get_voice(self, voice_id: str) -> Dict[str, Any]:
        """Get specific voice"""
        return self._request('GET', f'/voices/{voice_id}')
    
    def create_voice(self, name: str, files: List, **params) -> Dict[str, Any]:
        """Create custom voice"""
        file_data = [('files', f) for f in files]
        data = {'name': name, **params}
        
        headers = {'Authorization': f'Bearer {self.api_key}'}
        response = requests.post(
            f"{self.base_url}/voices",
            headers=headers,
            files=file_data,
            data=data
        )
        response.raise_for_status()
        return response.json()
    
    def update_voice(self, voice_id: str, **params) -> Dict[str, Any]:
        """Update voice"""
        return self._request('PUT', f'/voices/{voice_id}', json=params)
    
    def delete_voice(self, voice_id: str) -> None:
        """Delete voice"""
        self._request('DELETE', f'/voices/{voice_id}')
    
    # Auth Methods
    def sign_up(self, email: str, password: str, **params) -> Dict[str, Any]:
        """Register new user"""
        data = {'email': email, 'password': password, **params}
        return self._request('POST', '/auth/signup', json=data)
    
    def sign_in(self, email: str, password: str) -> Dict[str, Any]:
        """Login user"""
        data = {'email': email, 'password': password}
        return self._request('POST', '/auth/login', json=data)
    
    def get_profile(self) -> Dict[str, Any]:
        """Get user profile"""
        return self._request('GET', '/auth/me')
    
    def update_profile(self, **params) -> Dict[str, Any]:
        """Update user profile"""
        return self._request('PUT', '/auth/profile', json=params)
    
    # Workspace Methods
    def get_workspaces(self) -> List[Dict[str, Any]]:
        """Get all workspaces"""
        return self._request('GET', '/workspaces')
    
    def create_workspace(self, name: str, **params) -> Dict[str, Any]:
        """Create workspace"""
        data = {'name': name, **params}
        return self._request('POST', '/workspaces', json=data)
    
    # Billing Methods
    def get_plans(self) -> List[Dict[str, Any]]:
        """Get available plans"""
        return self._request('GET', '/plans')
    
    def get_current_plan(self) -> Dict[str, Any]:
        """Get current subscription"""
        return self._request('GET', '/billing/current-plan')
    
    def subscribe(self, plan_id: str) -> Dict[str, Any]:
        """Subscribe to plan"""
        return self._request('POST', '/billing/subscribe', json={'plan_id': plan_id})
    
    # Analytics
    def get_usage(self) -> Dict[str, Any]:
        """Get usage statistics"""
        return self._request('GET', '/analytics/usage')
    
    # API Keys
    def get_api_keys(self) -> List[Dict[str, Any]]:
        """Get all API keys"""
        return self._request('GET', '/developer/api')
    
    def create_api_key(self, name: str) -> Dict[str, Any]:
        """Create API key"""
        return self._request('POST', '/developer/api', json={'name': name})
    
    def delete_api_key(self, key_id: str) -> None:
        """Delete API key"""
        self._request('DELETE', f'/developer/api/{key_id}')
    
    # Webhooks
    def get_webhooks(self) -> List[Dict[str, Any]]:
        """Get all webhooks"""
        return self._request('GET', '/webhooks')
    
    def create_webhook(self, url: str, events: List[str], **params) -> Dict[str, Any]:
        """Create webhook"""
        data = {'url': url, 'events': events, **params}
        return self._request('POST', '/webhooks', json=data)
    
    def delete_webhook(self, webhook_id: str) -> None:
        """Delete webhook"""
        self._request('DELETE', f'/webhooks/{webhook_id}')
