/**
 * SPORE API Client
 * Generated from api/openapi.yaml
 */

class SporeApiClient {
  constructor(baseUrl) {
    if (!baseUrl) {
      throw new Error('baseUrl is required for SporeApiClient');
    }
    this.baseUrl = baseUrl;
    this.defaultHeaders = {
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    };
  }

  /**
   * Make an HTTP request
   * @param {string} method - HTTP method
   * @param {string} path - API path
   * @param {Object} options - Request options
   * @returns {Promise<Object>} Response data
   */
  async request(method, path, options = {}) {
    const url = `${this.baseUrl}${path}`;
    const config = {
      method,
      headers: { ...this.defaultHeaders, ...options.headers },
      ...options
    };

    try {
      const response = await fetch(url, config);
      
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      // Handle empty responses
      const contentType = response.headers.get('content-type');
      if (contentType && contentType.includes('application/json')) {
        return await response.json();
      }
      
      return await response.text();
    } catch (error) {
      throw new Error(`Request failed: ${error.message}`);
    }
  }

  /**
   * Get comprehensive task status
   * @returns {Promise<Object>} Task status response
   */
  async getTaskStatus() {
    return this.request('GET', '/api/tasks/status');
  }

  /**
   * Control individual task operations
   * @param {string} task - Name of the task to control
   * @param {string} action - Action to perform (enable, disable, start, stop, status)
   * @returns {Promise<Object>} Task control response
   */
  async controlTask(task, action) {
    const formData = new URLSearchParams();
    formData.append('task', task);
    formData.append('action', action);

    return this.request('POST', '/api/tasks/control', {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: formData.toString()
    });
  }

  /**
   * Get system status and API information
   * @returns {Promise<Object>} System status response
   */
  async getSystemStatus() {
    return this.request('GET', '/api/node/status');
  }

  /**
   * Get node endpoints
   * @returns {Promise<Object>} endpoints response
   */
  async getCapabilities() {
    return this.request('GET', '/api/node/endpoints');
  }

  /**
   * Get cluster discovery information
   * @returns {Promise<Object>} Cluster discovery response
   */
  async getClusterDiscovery() {
    return this.request('GET', '/api/cluster/members');
  }

  /**
   * Get cluster status
   * @returns {Promise<Object>} Cluster status response
   */
  async getClusterStatus() {
    return this.request('GET', '/api/cluster/members');
  }

  /**
   * Get OTA update status
   * @returns {Promise<Object>} OTA update status response
   */
  async getOtaStatus() {
    return this.request('GET', '/api/ota/status');
  }

  /**
   * Get system health metrics
   * @returns {Promise<Object>} Health metrics response
   */
  async getHealthMetrics() {
    return this.request('GET', '/api/health/metrics');
  }

  /**
   * Get system logs
   * @param {Object} options - Query options
   * @returns {Promise<Object>} System logs response
   */
  async getSystemLogs(options = {}) {
    const queryParams = new URLSearchParams();
    if (options.level) queryParams.append('level', options.level);
    if (options.limit) queryParams.append('limit', options.limit);
    if (options.offset) queryParams.append('offset', options.offset);

    const queryString = queryParams.toString();
    const path = queryString ? `/api/system/logs?${queryString}` : '/api/system/logs';
    
    return this.request('GET', path);
  }

  /**
   * Get network configuration
   * @returns {Promise<Object>} Network configuration response
   */
  async getNetworkConfig() {
    return this.request('GET', '/api/network/config');
  }

  /**
   * Update network configuration
   * @param {Object} config - Network configuration
   * @returns {Promise<Object>} Update response
   */
  async updateNetworkConfig(config) {
    return this.request('POST', '/api/network/config', {
      body: JSON.stringify(config)
    });
  }

  /**
   * Get WiFi networks
   * @returns {Promise<Object>} WiFi networks response
   */
  async getWifiNetworks() {
    return this.request('GET', '/api/network/wifi/scan');
  }

  /**
   * Connect to WiFi network
   * @param {string} ssid - Network SSID
   * @param {string} password - Network password
   * @returns {Promise<Object>} Connection response
   */
  async connectWifi(ssid, password) {
    return this.request('POST', '/api/network/wifi/connect', {
      body: JSON.stringify({ ssid, password })
    });
  }

  /**
   * Get device information
   * @returns {Promise<Object>} Device info response
   */
  async getDeviceInfo() {
    return this.request('GET', '/api/device/info');
  }

  /**
   * Restart the device
   * @returns {Promise<Object>} Restart response
   */
  async restartDevice() {
    return this.request('POST', '/api/device/restart');
  }

  /**
   * Factory reset the device
   * @returns {Promise<Object>} Factory reset response
   */
  async factoryReset() {
    return this.request('POST', '/api/device/factory-reset');
  }

  /**
   * Update firmware on the device
   * @param {Buffer|Uint8Array} firmwareData - Firmware binary data
   * @param {string} filename - Name of the firmware file
   * @returns {Promise<Object>} Update response
   */
  async updateFirmware(firmwareData, filename) {
    // Create multipart form data manually for Node.js compatibility
    const boundary = '----WebKitFormBoundary' + Math.random().toString(16).substr(2, 8);
    
    let body = '';
    
    // Add the firmware file part
    body += `--${boundary}\r\n`;
    body += `Content-Disposition: form-data; name="firmware"; filename="${filename}"\r\n`;
    body += 'Content-Type: application/octet-stream\r\n\r\n';
    
    // Convert the body to Buffer and append the firmware data
    const headerBuffer = Buffer.from(body, 'utf8');
    const endBuffer = Buffer.from(`\r\n--${boundary}--\r\n`, 'utf8');
    
    // Combine all parts
    const finalBody = Buffer.concat([headerBuffer, firmwareData, endBuffer]);
    
    // Send the multipart form data to the SPORE device
    return this.request('POST', '/api/node/update', {
      body: finalBody,
      headers: {
        'Content-Type': `multipart/form-data; boundary=${boundary}`
      }
    });
  }
}

// Export the client class
module.exports = SporeApiClient;

// Also export for ES modules if available
if (typeof exports !== 'undefined') {
  if (typeof module !== 'undefined' && module.exports) {
    exports = module.exports = SporeApiClient;
  }
} 