"""
RecHost.eu API SDK for Python
Version: 1.0.0
Author: RecHost.eu
"""

import requests
from typing import Dict, List, Optional, Union
from requests.exceptions import RequestException, Timeout


class RecHostAPI:
    """RecHost.eu API Client"""

    def __init__(self, api_key: Optional[str] = None, base_url: str = "https://api.rechost.eu/v1", timeout: int = 10):
        """
        Initialize API client
        
        Args:
            api_key: Optional API key for authenticated requests
            base_url: Base URL for API (default: https://api.rechost.eu/v1)
            timeout: Request timeout in seconds (default: 10)
        """
        self.base_url = base_url.rstrip('/')
        self.api_key = api_key
        self.timeout = timeout
        self.session = requests.Session()
        
        if api_key:
            self.session.headers.update({'X-API-Key': api_key})

    def _request(self, endpoint: str, method: str = 'GET', data: Optional[Dict] = None) -> Dict:
        """
        Make HTTP request
        
        Args:
            endpoint: API endpoint
            method: HTTP method (GET or POST)
            data: Request data for POST requests
            
        Returns:
            dict: Response data
            
        Raises:
            RecHostAPIError: If request fails
        """
        url = f"{self.base_url}{endpoint}"
        
        try:
            if method == 'GET':
                response = self.session.get(url, timeout=self.timeout)
            elif method == 'POST':
                response = self.session.post(url, json=data, timeout=self.timeout)
            else:
                raise ValueError(f"Unsupported method: {method}")
            
            response.raise_for_status()
            return response.json()
            
        except Timeout:
            raise RecHostAPIError("Request timeout", 408)
        except RequestException as e:
            if hasattr(e.response, 'json'):
                try:
                    error_data = e.response.json()
                    raise RecHostAPIError(
                        error_data.get('message', str(e)),
                        e.response.status_code,
                        error_data
                    )
                except:
                    pass
            raise RecHostAPIError(str(e))

    def get_status(self, ip: str, port: int, retries: int = 3) -> Dict:
        """
        Get server status
        
        Args:
            ip: Server IP address
            port: Server port
            retries: Number of retry attempts (1-5)
            
        Returns:
            dict: Server status information
        """
        params = f"?ip={ip}&port={port}&retries={retries}"
        return self._request(f"/status{params}")

    def check_batch(self, servers: List[Dict[str, Union[str, int]]]) -> Dict:
        """
        Check multiple servers at once
        
        Args:
            servers: List of servers [{'ip': 'x.x.x.x', 'port': 25565}, ...]
            
        Returns:
            dict: Batch check results
        """
        return self._request('/batch', 'POST', {'servers': servers})

    def lookup(self, ip: str) -> Dict:
        """
        Lookup server ports
        
        Args:
            ip: Server IP address
            
        Returns:
            dict: Port scan results
        """
        return self._request(f"/lookup?ip={ip}")

    def get_server_info(self, server_id: Optional[int] = None, ip: Optional[str] = None, port: Optional[int] = None) -> Dict:
        """
        Get server info (RecHost servers only)
        
        Args:
            server_id: RecHost server ID
            ip: Server IP address (used with port)
            port: Server port (used with ip)
            
        Returns:
            dict: Server information
            
        Raises:
            ValueError: If neither server_id nor ip+port provided
        """
        if server_id:
            params = f"?server_id={server_id}"
        elif ip and port:
            params = f"?ip={ip}&port={port}"
        else:
            raise ValueError("Either server_id or ip+port must be provided")
        
        if self.api_key:
            params += f"&api_key={self.api_key}"
        
        return self._request(f"/serverinfo{params}")

    def is_online(self, ip: str, port: int) -> bool:
        """
        Check if server is online
        
        Args:
            ip: Server IP address
            port: Server port
            
        Returns:
            bool: True if server is online
        """
        try:
            response = self.get_status(ip, port)
            return response.get('success') and response.get('status', {}).get('online')
        except RecHostAPIError:
            return False

    def get_players(self, ip: str, port: int) -> Dict[str, int]:
        """
        Get player count
        
        Args:
            ip: Server IP address
            port: Server port
            
        Returns:
            dict: Player information {'online': 0, 'max': 0}
        """
        try:
            response = self.get_status(ip, port)
            if response.get('success') and response.get('status', {}).get('online'):
                return response['status']['players']
        except RecHostAPIError:
            pass
        return {'online': 0, 'max': 0}


class RecHostAPIError(Exception):
    """Custom exception for API errors"""
    
    def __init__(self, message: str, status_code: int = 500, response: Optional[Dict] = None):
        super().__init__(message)
        self.status_code = status_code
        self.response = response


# Example usage:
if __name__ == '__main__':
    # Initialize API client
    api = RecHostAPI(
        api_key='your-api-key',  # optional
        timeout=5
    )

    # Check single server
    status = api.get_status('mc.hypixel.net', 25565)
    print(f"Server is {'ONLINE' if status['status']['online'] else 'OFFLINE'}")
    print(f"Players: {status['status']['players']['online']}/{status['status']['players']['max']}")

    # Check multiple servers
    batch = api.check_batch([
        {'ip': 'mc.hypixel.net', 'port': 25565},
        {'ip': '1.2.3.4', 'port': 30120}
    ])
    print(f"Online: {batch['summary']['online']}/{batch['summary']['total']}")

    # Lookup server
    lookup = api.lookup('example.com')
    for port in lookup['open_ports']:
        print(f"Port {port['port']} ({port['type']}) is OPEN")

    # Helper methods
    is_online = api.is_online('mc.hypixel.net', 25565)
    players = api.get_players('mc.hypixel.net', 25565)
    print(f"Online: {is_online}, Players: {players}")
