/**
 * BreakPilot Studio - API Helpers Module
 *
 * Gemeinsame Funktionen für API-Aufrufe und Status-Verwaltung:
 * - fetchJSON: Wrapper für fetch mit Error-Handling
 * - postJSON: POST-Requests mit JSON-Body
 * - setStatus: Status-Leiste aktualisieren
 * - showNotification: Toast-Benachrichtigungen
 *
 * Refactored: 2026-01-19
 */

import { t } from './i18n.js';

// Status-Bar Element-Referenzen (werden bei init gesetzt)
let statusBar = null;
let statusDot = null;
let statusMain = null;
let statusSub = null;

/**
 * Initialisiert die Status-Bar Referenzen
 * Sollte beim DOMContentLoaded aufgerufen werden
 */
export function initStatusBar() {
  statusBar = document.getElementById('status-bar');
  statusDot = document.getElementById('status-dot');
  statusMain = document.getElementById('status-main');
  statusSub = document.getElementById('status-sub');
}

/**
 * Setzt den Status in der Status-Leiste
 * @param {string} type - 'ready'|'working'|'success'|'error'
 * @param {string} main - Haupttext
 * @param {string} [sub] - Optionaler Untertext
 */
export function setStatus(type, main, sub = '') {
  if (!statusBar || !statusDot || !statusMain) {
    console.log(`[Status ${type}]: ${main}`, sub);
    return;
  }

  // Alle Status-Klassen entfernen
  statusBar.classList.remove('status-ready', 'status-working', 'status-success', 'status-error');
  statusDot.classList.remove('dot-ready', 'dot-working', 'dot-success', 'dot-error');

  // Neue Status-Klasse setzen
  statusBar.classList.add(`status-${type}`);
  statusDot.classList.add(`dot-${type}`);

  // Texte setzen
  statusMain.textContent = main;
  if (statusSub) {
    statusSub.textContent = sub;
  }
}

/**
 * Setzt den Status auf "Bereit"
 */
export function setStatusReady() {
  setStatus('ready', t('status_ready') || 'Bereit', '');
}

/**
 * Setzt den Status auf "Arbeitet..."
 * @param {string} message - Was gerade gemacht wird
 */
export function setStatusWorking(message) {
  setStatus('working', message, '');
}

/**
 * Setzt den Status auf "Erfolg"
 * @param {string} message - Erfolgsmeldung
 * @param {string} [details] - Optionale Details
 */
export function setStatusSuccess(message, details = '') {
  setStatus('success', message, details);
}

/**
 * Setzt den Status auf "Fehler"
 * @param {string} message - Fehlermeldung
 * @param {string} [details] - Optionale Details
 */
export function setStatusError(message, details = '') {
  setStatus('error', message, details);
}

/**
 * Führt einen GET-Request aus und parst JSON
 * @param {string} url - Die URL
 * @param {Object} [options] - Zusätzliche fetch-Optionen
 * @returns {Promise<any>} - Das geparste JSON
 * @throws {Error} - Bei Netzwerk- oder Parse-Fehlern
 */
export async function fetchJSON(url, options = {}) {
  const response = await fetch(url, {
    ...options,
    headers: {
      'Accept': 'application/json',
      ...options.headers,
    },
  });

  if (!response.ok) {
    const errorText = await response.text().catch(() => 'Unknown error');
    throw new Error(`HTTP ${response.status}: ${errorText}`);
  }

  return response.json();
}

/**
 * Führt einen POST-Request mit JSON-Body aus
 * @param {string} url - Die URL
 * @param {Object} data - Die zu sendenden Daten
 * @param {Object} [options] - Zusätzliche fetch-Optionen
 * @returns {Promise<any>} - Das geparste JSON
 * @throws {Error} - Bei Netzwerk- oder Parse-Fehlern
 */
export async function postJSON(url, data = {}, options = {}) {
  const response = await fetch(url, {
    method: 'POST',
    ...options,
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      ...options.headers,
    },
    body: JSON.stringify(data),
  });

  if (!response.ok) {
    const errorText = await response.text().catch(() => 'Unknown error');
    throw new Error(`HTTP ${response.status}: ${errorText}`);
  }

  return response.json();
}

/**
 * Führt einen POST-Request ohne Body aus (für Trigger-Endpoints)
 * @param {string} url - Die URL
 * @param {Object} [options] - Zusätzliche fetch-Optionen
 * @returns {Promise<any>} - Das geparste JSON
 */
export async function postTrigger(url, options = {}) {
  const response = await fetch(url, {
    method: 'POST',
    ...options,
    headers: {
      'Accept': 'application/json',
      ...options.headers,
    },
  });

  if (!response.ok) {
    const errorText = await response.text().catch(() => 'Unknown error');
    throw new Error(`HTTP ${response.status}: ${errorText}`);
  }

  return response.json();
}

/**
 * Führt einen DELETE-Request aus
 * @param {string} url - Die URL
 * @param {Object} [options] - Zusätzliche fetch-Optionen
 * @returns {Promise<any>} - Das geparste JSON
 */
export async function deleteRequest(url, options = {}) {
  const response = await fetch(url, {
    method: 'DELETE',
    ...options,
    headers: {
      'Accept': 'application/json',
      ...options.headers,
    },
  });

  if (!response.ok) {
    const errorText = await response.text().catch(() => 'Unknown error');
    throw new Error(`HTTP ${response.status}: ${errorText}`);
  }

  return response.json();
}

/**
 * Lädt eine Datei hoch
 * @param {string} url - Die Upload-URL
 * @param {File|FormData} file - Die Datei oder FormData
 * @param {function} [onProgress] - Progress-Callback (0-100)
 * @returns {Promise<any>} - Das geparste JSON
 */
export async function uploadFile(url, file, onProgress = null) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    xhr.open('POST', url);

    if (onProgress && xhr.upload) {
      xhr.upload.addEventListener('progress', (e) => {
        if (e.lengthComputable) {
          const percent = Math.round((e.loaded / e.total) * 100);
          onProgress(percent);
        }
      });
    }

    xhr.onload = () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        try {
          resolve(JSON.parse(xhr.responseText));
        } catch (e) {
          resolve({ status: 'OK', message: xhr.responseText });
        }
      } else {
        reject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`));
      }
    };

    xhr.onerror = () => reject(new Error('Network error during upload'));

    // FormData erstellen falls nötig
    let formData;
    if (file instanceof FormData) {
      formData = file;
    } else {
      formData = new FormData();
      formData.append('file', file);
    }

    xhr.send(formData);
  });
}

/**
 * Zeigt eine kurze Benachrichtigung (Toast)
 * @param {string} message - Die Nachricht
 * @param {string} [type='info'] - 'info'|'success'|'error'|'warning'
 * @param {number} [duration=3000] - Anzeigedauer in ms
 */
export function showNotification(message, type = 'info', duration = 3000) {
  // Prüfe ob Toast-Container existiert, sonst erstellen
  let container = document.getElementById('toast-container');
  if (!container) {
    container = document.createElement('div');
    container.id = 'toast-container';
    container.style.cssText = 'position:fixed;top:16px;right:16px;z-index:10000;display:flex;flex-direction:column;gap:8px;';
    document.body.appendChild(container);
  }

  // Toast erstellen
  const toast = document.createElement('div');
  toast.className = `toast toast-${type}`;
  toast.style.cssText = `
    padding: 12px 16px;
    border-radius: 8px;
    background: var(--bp-card-bg, #1e293b);
    color: var(--bp-text, #e2e8f0);
    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
    font-size: 13px;
    animation: slideIn 0.3s ease;
    border-left: 4px solid ${type === 'success' ? '#22c55e' : type === 'error' ? '#ef4444' : type === 'warning' ? '#f59e0b' : '#3b82f6'};
  `;
  toast.textContent = message;

  container.appendChild(toast);

  // Nach duration entfernen
  setTimeout(() => {
    toast.style.animation = 'slideOut 0.3s ease';
    setTimeout(() => toast.remove(), 300);
  }, duration);
}

/**
 * Wrapper für API-Aufrufe mit Status-Anzeige und Error-Handling
 * @param {function} apiCall - Die async API-Funktion
 * @param {Object} options - Optionen
 * @param {string} options.workingMessage - Nachricht während des Ladens
 * @param {string} options.successMessage - Nachricht bei Erfolg
 * @param {string} options.errorMessage - Nachricht bei Fehler
 * @returns {Promise<any>} - Das Ergebnis oder null bei Fehler
 */
export async function withStatus(apiCall, options = {}) {
  const {
    workingMessage = 'Wird geladen...',
    successMessage = 'Erfolgreich',
    errorMessage = 'Fehler',
  } = options;

  setStatusWorking(workingMessage);

  try {
    const result = await apiCall();
    setStatusSuccess(successMessage);
    return result;
  } catch (error) {
    console.error(errorMessage, error);
    setStatusError(errorMessage, String(error.message || error));
    return null;
  }
}

/**
 * Debounce-Funktion für häufige Events
 * @param {function} func - Die zu debouncende Funktion
 * @param {number} wait - Wartezeit in ms
 * @returns {function} - Die gedebouncte Funktion
 */
export function debounce(func, wait) {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}

/**
 * Throttle-Funktion für Rate-Limiting
 * @param {function} func - Die zu throttlende Funktion
 * @param {number} limit - Minimaler Abstand in ms
 * @returns {function} - Die gethrottlete Funktion
 */
export function throttle(func, limit) {
  let inThrottle;
  return function(...args) {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

// CSS für Toast-Animationen (einmal injizieren)
if (typeof document !== 'undefined' && !document.getElementById('toast-styles')) {
  const style = document.createElement('style');
  style.id = 'toast-styles';
  style.textContent = `
    @keyframes slideIn {
      from { transform: translateX(100%); opacity: 0; }
      to { transform: translateX(0); opacity: 1; }
    }
    @keyframes slideOut {
      from { transform: translateX(0); opacity: 1; }
      to { transform: translateX(100%); opacity: 0; }
    }
  `;
  document.head.appendChild(style);
}
