/**
 * APIClient - Client API pour les communications avec le backend FastAPI
 * 
 * Responsabilités:
 * - Encapsuler toutes les communications avec l'API
 * - Gérer les erreurs réseau avec retry et backoff exponentiel
 * - Gérer le cache des documents dans localStorage
 * - Fournir des méthodes pour tous les endpoints
 * 
 * Validates: Requirements 14.1, 14.2, 14.4, 12.4, 12.5
 */
class APIClient {
  constructor(baseURL = '') {
    this.baseURL = baseURL;
    this.maxRetries = 3;
  }

  /**
   * Attendre un délai (pour retry avec backoff)
   */
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * Fetch avec retry et backoff exponentiel
   * Validates: Requirements 14.1
   */
  async fetchWithRetry(url, options = {}, retries = this.maxRetries) {
    for (let i = 0; i < retries; i++) {
      try {
        const response = await fetch(url, {
          ...options,
          headers: {
            'Content-Type': 'application/json',
            ...options.headers
          }
        });

        if (!response.ok) {
          throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }

        return response;
      } catch (error) {
        if (i === retries - 1) {
          // Dernier essai échoué
          this.handleNetworkError(error);
          throw error;
        }
        // Attendre avant de réessayer (backoff exponentiel)
        await this.sleep(Math.pow(2, i) * 1000);
      }
    }
  }

  /**
   * Gérer les erreurs réseau
   * Validates: Requirements 14.1
   */
  handleNetworkError(error) {
    console.error('Network error:', error);
    const message = `Erreur réseau: ${error.message}. Vérifiez votre connexion.`;
    this.showError(message, 'Réessayer', () => window.location.reload());
  }

  /**
   * Gérer les erreurs API selon le code HTTP
   * Validates: Requirements 14.2, 14.4
   */
  handleAPIError(response, context = '') {
    const errorMessages = {
      400: 'Requête invalide. Vérifiez les données saisies.',
      401: 'Non autorisé. Veuillez vous reconnecter.',
      403: 'Accès interdit. Vous n\'avez pas les permissions nécessaires.',
      404: `${context} introuvable.`,
      500: 'Erreur serveur. Veuillez réessayer plus tard.',
      503: 'Service temporairement indisponible.'
    };

    const message = errorMessages[response.status] || 
                    `Erreur ${response.status}: ${response.statusText}`;
    
    console.error(`API Error [${response.status}]:`, context, response);
    this.showError(message);
    
    return { error: true, status: response.status, message };
  }

  /**
   * Afficher un message d'erreur (à implémenter avec un système de notification)
   */
  showError(message, actionLabel = null, onAction = null) {
    // Pour l'instant, utiliser alert (sera remplacé par un système de notification)
    alert(message);
    if (actionLabel && onAction) {
      if (confirm(actionLabel)) {
        onAction();
      }
    }
  }

  // ===== ENDPOINTS API =====

  /**
   * Charger un séjour complet avec proposition de codage et faits cliniques
   */
  async loadStay(stayId) {
    try {
      const [proposal, facts] = await Promise.all([
        this.getCodingProposal(stayId),
        this.getClinicalFacts(stayId)
      ]);
      return { proposal, facts };
    } catch (error) {
      console.error('Error loading stay:', error);
      throw error;
    }
  }

  /**
   * Récupérer la proposition de codage d'un séjour
   */
  async getCodingProposal(stayId) {
    const url = `${this.baseURL}/stays/${stayId}/coding-proposal`;
    const response = await this.fetchWithRetry(url);
    return await response.json();
  }

  /**
   * Récupérer les faits cliniques d'un séjour
   * Validates: Requirements 6.1, 6.2, 6.3, 6.4
   */
  async getClinicalFacts(stayId) {
    const url = `${this.baseURL}/stays/${stayId}/clinical-facts`;
    try {
      const response = await this.fetchWithRetry(url);
      return await response.json();
    } catch (error) {
      if (error.message.includes('404')) {
        this.handleAPIError({ status: 404 }, `Séjour ${stayId}`);
      }
      throw error;
    }
  }

  /**
   * Récupérer un document avec cache
   * Validates: Requirements 12.4, 12.5
   */
  async getDocument(documentId) {
    // Vérifier le cache d'abord
    const cached = this.getDocumentFromCache(documentId);
    if (cached) {
      console.log(`Document ${documentId} loaded from cache`);
      return cached;
    }

    // Charger depuis l'API
    const url = `${this.baseURL}/documents/${documentId}`;
    try {
      const response = await this.fetchWithRetry(url);
      const document = await response.json();
      
      // Mettre en cache
      this.cacheDocument(documentId, document);
      
      return document;
    } catch (error) {
      if (error.message.includes('404')) {
        this.handleAPIError({ status: 404 }, `Document ${documentId}`);
      }
      throw error;
    }
  }

  /**
   * Récupérer un document depuis le cache localStorage
   */
  getDocumentFromCache(documentId) {
    try {
      const cache = localStorage.getItem('tim_documents_cache');
      if (cache) {
        const parsed = JSON.parse(cache);
        return parsed[documentId] || null;
      }
    } catch (error) {
      console.error('Error reading document cache:', error);
    }
    return null;
  }

  /**
   * Mettre un document en cache dans localStorage
   */
  cacheDocument(documentId, document) {
    try {
      const cache = localStorage.getItem('tim_documents_cache');
      const parsed = cache ? JSON.parse(cache) : {};
      parsed[documentId] = document;
      localStorage.setItem('tim_documents_cache', JSON.stringify(parsed));
    } catch (error) {
      console.error('Error caching document:', error);
    }
  }

  /**
   * Enregistrer une correction de code
   */
  async correctCode(stayId, correction) {
    const url = `${this.baseURL}/stays/${stayId}/correct-code`;
    try {
      const response = await this.fetchWithRetry(url, {
        method: 'POST',
        body: JSON.stringify(correction)
      });
      return await response.json();
    } catch (error) {
      this.handleAPIError({ status: 500 }, 'Correction');
      throw error;
    }
  }

  /**
   * Valider un séjour
   */
  async validateStay(stayId, validation) {
    const url = `${this.baseURL}/stays/${stayId}/validate`;
    try {
      const response = await this.fetchWithRetry(url, {
        method: 'POST',
        body: JSON.stringify(validation)
      });
      return await response.json();
    } catch (error) {
      this.handleAPIError({ status: 500 }, 'Validation');
      throw error;
    }
  }

  /**
   * Ajouter un commentaire
   */
  async addComment(stayId, comment) {
    const url = `${this.baseURL}/stays/${stayId}/comment`;
    try {
      const response = await this.fetchWithRetry(url, {
        method: 'POST',
        body: JSON.stringify(comment)
      });
      return await response.json();
    } catch (error) {
      this.handleAPIError({ status: 500 }, 'Commentaire');
      throw error;
    }
  }

  /**
   * Exporter en PDF
   * Validates: Requirements 11.1, 11.2
   */
  async exportPDF(stayId, options = {}) {
    const url = `${this.baseURL}/stays/${stayId}/export-pdf`;
    try {
      const response = await this.fetchWithRetry(url, {
        method: 'POST',
        body: JSON.stringify({
          include_documents: true,
          include_evidence: true,
          include_corrections: true,
          ...options
        })
      });
      const result = await response.json();
      
      // Télécharger automatiquement le PDF
      if (result.pdf_url) {
        window.location.href = this.baseURL + result.pdf_url;
      }
      
      return result;
    } catch (error) {
      this.handleAPIError({ status: 500 }, 'Export PDF');
      throw error;
    }
  }

  /**
   * Exporter l'audit
   */
  async exportAudit(stayId, options = {}) {
    const url = `${this.baseURL}/stays/${stayId}/audit/export`;
    try {
      const response = await this.fetchWithRetry(url, {
        method: 'POST',
        body: JSON.stringify(options)
      });
      return await response.json();
    } catch (error) {
      this.handleAPIError({ status: 500 }, 'Export Audit');
      throw error;
    }
  }
}

// Export pour utilisation dans d'autres modules
if (typeof module !== 'undefined' && module.exports) {
  module.exports = APIClient;
}
