<?php
/**
 * RecHost.eu API SDK for PHP
 * @version 1.0.0
 * @author RecHost.eu
 */

class RecHostAPI
{
    private $baseURL;
    private $apiKey;
    private $timeout;

    /**
     * @param array $config Configuration options
     */
    public function __construct($config = [])
    {
        $this->baseURL = $config['baseURL'] ?? 'https://api.rechost.eu/v1';
        $this->apiKey = $config['apiKey'] ?? null;
        $this->timeout = $config['timeout'] ?? 10;
    }

    /**
     * Make HTTP request
     * @throws RecHostAPIException
     */
    private function request($endpoint, $method = 'GET', $data = null)
    {
        $url = $this->baseURL . $endpoint;

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

        $headers = ['Content-Type: application/json'];
        if ($this->apiKey) {
            $headers[] = 'X-API-Key: ' . $this->apiKey;
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            if ($data) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            }
        }

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            throw new RecHostAPIException("cURL Error: $error", 0);
        }

        $decoded = json_decode($response, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new RecHostAPIException("Invalid JSON response", $httpCode);
        }

        if ($httpCode >= 400) {
            throw new RecHostAPIException(
                $decoded['message'] ?? "HTTP Error $httpCode",
                $httpCode,
                $decoded
            );
        }

        return $decoded;
    }

    /**
     * Get server status
     * @param string $ip Server IP address
     * @param int $port Server port
     * @param int $retries Number of retry attempts
     * @return array
     */
    public function getStatus($ip, $port, $retries = 3)
    {
        $params = http_build_query([
            'ip' => $ip,
            'port' => $port,
            'retries' => $retries
        ]);
        return $this->request("/status?$params");
    }

    /**
     * Check multiple servers at once
     * @param array $servers Array of ['ip' => 'x.x.x.x', 'port' => 25565]
     * @return array
     */
    public function checkBatch($servers)
    {
        return $this->request('/batch', 'POST', ['servers' => $servers]);
    }

    /**
     * Lookup server ports
     * @param string $ip Server IP address
     * @return array
     */
    public function lookup($ip)
    {
        return $this->request("/lookup?ip=" . urlencode($ip));
    }

    /**
     * Get server info (RecHost servers only)
     * @param array $params Either ['serverId' => 123] or ['ip' => 'x.x.x.x', 'port' => 25565]
     * @return array
     */
    public function getServerInfo($params)
    {
        $query = [];

        if (isset($params['serverId'])) {
            $query['server_id'] = $params['serverId'];
        } elseif (isset($params['ip']) && isset($params['port'])) {
            $query['ip'] = $params['ip'];
            $query['port'] = $params['port'];
        } else {
            throw new RecHostAPIException('Either serverId or ip+port must be provided');
        }

        if ($this->apiKey) {
            $query['api_key'] = $this->apiKey;
        }

        return $this->request('/serverinfo?' . http_build_query($query));
    }

    /**
     * Check if server is online
     * @param string $ip
     * @param int $port
     * @return bool
     */
    public function isOnline($ip, $port)
    {
        try {
            $response = $this->getStatus($ip, $port);
            return $response['success'] && $response['status']['online'];
        } catch (RecHostAPIException $e) {
            return false;
        }
    }

    /**
     * Get player count
     * @param string $ip
     * @param int $port
     * @return array ['online' => 0, 'max' => 0]
     */
    public function getPlayers($ip, $port)
    {
        try {
            $response = $this->getStatus($ip, $port);
            if ($response['success'] && $response['status']['online']) {
                return $response['status']['players'];
            }
        } catch (RecHostAPIException $e) {
            // Fall through
        }
        return ['online' => 0, 'max' => 0];
    }
}

/**
 * Custom exception for API errors
 */
class RecHostAPIException extends Exception
{
    public $response;

    public function __construct($message, $code = 0, $response = null)
    {
        parent::__construct($message, $code);
        $this->response = $response;
    }
}

// Example usage:
/*
require_once 'rechost-api.php';

$api = new RecHostAPI([
    'apiKey' => 'your-api-key', // optional
    'timeout' => 5
]);

// Check single server
$status = $api->getStatus('mc.hypixel.net', 25565);
echo "Server is " . ($status['status']['online'] ? 'ONLINE' : 'OFFLINE') . "\n";
echo "Players: {$status['status']['players']['online']}/{$status['status']['players']['max']}\n";

// Check multiple servers
$batch = $api->checkBatch([
    ['ip' => 'mc.hypixel.net', 'port' => 25565],
    ['ip' => '1.2.3.4', 'port' => 30120]
]);
echo "Online: {$batch['summary']['online']}/{$batch['summary']['total']}\n";

// Lookup server
$lookup = $api->lookup('example.com');
foreach ($lookup['open_ports'] as $port) {
    echo "Port {$port['port']} ({$port['type']}) is OPEN\n";
}

// Helper methods
$isOnline = $api->isOnline('mc.hypixel.net', 25565);
$players = $api->getPlayers('mc.hypixel.net', 25565);
*/
