import ApiService from './ApiService';
import { MaterielBTP, RechercheMaterielParams } from './materielBTPService';
import { ZoneClimatique } from './zoneClimatiqueService';
import { ResultatCalculBriques, ResultatCalculBetonArme } from './calculsTechniquesService';

/**
 * Service d'export pour les données BTP ultra-détaillées
 * Permet l'export en CSV, Excel et PDF des matériaux, calculs et zones climatiques
 */

export type FormatExport = 'CSV' | 'EXCEL' | 'PDF';

export interface OptionsExport {
  format: FormatExport;
  includeImages?: boolean;
  includeCharts?: boolean;
  filtres?: any;
  colonnesPersonnalisees?: string[];
  template?: 'STANDARD' | 'DETAILLE' | 'RESUME';
}

export interface ResultatExport {
  filename: string;
  blob: Blob;
  size: number;
  format: FormatExport;
  nbLignes: number;
  dateGeneration: string;
}

export class ExportBTPService {

  /**
   * Export des matériaux BTP avec filtres
   */
  static async exporterMateriaux(options: OptionsExport & {
    filtres?: RechercheMaterielParams;
  }): Promise<ResultatExport> {
    try {
      const blob = await ApiService.post<Blob>(
        '/calculs-techniques/materiaux/export',
        {
          format: options.format,
          filtres: options.filtres,
          template: options.template || 'STANDARD',
          colonnesPersonnalisees: options.colonnesPersonnalisees
        },
        { responseType: 'blob' }
      );

      const filename = this.genererNomFichier('materiaux', options.format);
      
      return {
        filename,
        blob,
        size: blob.size,
        format: options.format,
        nbLignes: 0, // Sera calculé côté serveur
        dateGeneration: new Date().toISOString()
      };

    } catch (error) {
      console.error('Erreur export matériaux:', error);
      throw new Error('Impossible d\'exporter les matériaux');
    }
  }

  /**
   * Export des zones climatiques
   */
  static async exporterZonesClimatiques(options: OptionsExport): Promise<ResultatExport> {
    try {
      const blob = await ApiService.post<Blob>(
        '/calculs-techniques/zones-climatiques/export',
        {
          format: options.format,
          template: options.template || 'STANDARD'
        },
        { responseType: 'blob' }
      );

      const filename = this.genererNomFichier('zones-climatiques', options.format);
      
      return {
        filename,
        blob,
        size: blob.size,
        format: options.format,
        nbLignes: 0,
        dateGeneration: new Date().toISOString()
      };

    } catch (error) {
      console.error('Erreur export zones climatiques:', error);
      throw new Error('Impossible d\'exporter les zones climatiques');
    }
  }

  /**
   * Export des résultats de calculs techniques
   */
  static async exporterCalculs(
    calculs: Array<{
      type: 'BRIQUES' | 'BETON' | 'MORTIER';
      resultat: ResultatCalculBriques | ResultatCalculBetonArme | any;
      parametres: any;
    }>,
    options: OptionsExport
  ): Promise<ResultatExport> {
    try {
      const data = {
        calculs: calculs,
        format: options.format,
        template: options.template || 'DETAILLE',
        includeCharts: options.includeCharts || false
      };

      const blob = await ApiService.post<Blob>(
        '/calculs-techniques/export-calculs',
        data,
        { responseType: 'blob' }
      );

      const filename = this.genererNomFichier('calculs-techniques', options.format);
      
      return {
        filename,
        blob,
        size: blob.size,
        format: options.format,
        nbLignes: calculs.length,
        dateGeneration: new Date().toISOString()
      };

    } catch (error) {
      // Fallback : export côté client si serveur indisponible
      console.warn('Export serveur indisponible, génération côté client');
      return this.exporterCalculsCoteClient(calculs, options);
    }
  }

  /**
   * Export complet du projet BTP (matériaux + zones + calculs)
   */
  static async exporterProjetComplet(
    chantierId: string,
    options: OptionsExport & {
      includeMateriaux?: boolean;
      includeZones?: boolean;
      includeCalculs?: boolean;
      includePhases?: boolean;
    }
  ): Promise<ResultatExport> {
    try {
      const data = {
        chantierId,
        format: options.format,
        template: options.template || 'DETAILLE',
        sections: {
          materiaux: options.includeMateriaux !== false,
          zones: options.includeZones !== false,
          calculs: options.includeCalculs !== false,
          phases: options.includePhases !== false
        },
        includeCharts: options.includeCharts || false,
        includeImages: options.includeImages || false
      };

      const blob = await ApiService.post<Blob>(
        '/calculs-techniques/export-projet-complet',
        data,
        { responseType: 'blob' }
      );

      const filename = this.genererNomFichier(`projet-${chantierId}`, options.format);
      
      return {
        filename,
        blob,
        size: blob.size,
        format: options.format,
        nbLignes: 0,
        dateGeneration: new Date().toISOString()
      };

    } catch (error) {
      console.error('Erreur export projet complet:', error);
      throw new Error('Impossible d\'exporter le projet complet');
    }
  }

  /**
   * Génération de devis BTP détaillé avec matériaux et calculs
   */
  static async genererDevisBTP(
    devisData: {
      chantierId: string;
      phases: Array<{
        nom: string;
        materiaux: Array<{
          code: string;
          quantite: number;
          prixUnitaire?: number;
        }>;
        calculs?: any;
      }>;
      client: {
        nom: string;
        adresse: string;
        telephone?: string;
        email?: string;
      };
      options: {
        margeCommerciale: number;
        tva: number;
        delaiExecution: number;
        validiteDevis: number; // jours
        conditionsPaiement: string;
      };
    },
    format: FormatExport = 'PDF'
  ): Promise<ResultatExport> {
    try {
      const blob = await ApiService.post<Blob>(
        '/calculs-techniques/generer-devis',
        {
          ...devisData,
          format,
          template: 'DEVIS_PROFESSIONNEL'
        },
        { responseType: 'blob' }
      );

      const filename = this.genererNomFichier(`devis-${devisData.chantierId}`, format);
      
      return {
        filename,
        blob,
        size: blob.size,
        format,
        nbLignes: devisData.phases.length,
        dateGeneration: new Date().toISOString()
      };

    } catch (error) {
      console.error('Erreur génération devis:', error);
      throw new Error('Impossible de générer le devis');
    }
  }

  /**
   * Export des matériaux avec QR codes pour traçabilité
   */
  static async exporterMateriauxAvecQRCodes(
    materiaux: MaterielBTP[],
    options: OptionsExport
  ): Promise<ResultatExport> {
    try {
      const data = {
        materiaux: materiaux.map(m => ({
          id: m.id,
          code: m.code,
          nom: m.nom,
          categorie: m.categorie,
          specifications: {
            resistance: m.resistanceCompression,
            densite: m.densite,
            norme: m.normePrincipale
          }
        })),
        format: options.format,
        includeQRCodes: true,
        template: 'TRACABILITE'
      };

      const blob = await ApiService.post<Blob>(
        '/calculs-techniques/export-tracabilite',
        data,
        { responseType: 'blob' }
      );

      const filename = this.genererNomFichier('tracabilite-materiaux', options.format);
      
      return {
        filename,
        blob,
        size: blob.size,
        format: options.format,
        nbLignes: materiaux.length,
        dateGeneration: new Date().toISOString()
      };

    } catch (error) {
      console.error('Erreur export traçabilité:', error);
      throw new Error('Impossible d\'exporter la traçabilité');
    }
  }

  // =================== MÉTHODES UTILITAIRES ===================

  /**
   * Télécharge automatiquement le fichier exporté
   */
  static telechargerFichier(resultat: ResultatExport): void {
    const url = window.URL.createObjectURL(resultat.blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = resultat.filename;
    document.body.appendChild(a);
    a.click();
    window.URL.revokeObjectURL(url);
    document.body.removeChild(a);
  }

  /**
   * Prévisualise le contenu avant export (pour PDF)
   */
  static async previsualiserExport(
    type: 'MATERIAUX' | 'ZONES' | 'CALCULS' | 'DEVIS',
    donnees: any,
    options: OptionsExport
  ): Promise<string> {
    try {
      const response = await ApiService.post<{ previewUrl: string }>(
        '/calculs-techniques/previsualiser-export',
        {
          type,
          donnees,
          options
        }
      );

      return response.previewUrl;

    } catch (error) {
      console.error('Erreur prévisualisation:', error);
      throw new Error('Impossible de générer la prévisualisation');
    }
  }

  /**
   * Obtient les templates d'export disponibles
   */
  static async getTemplatesDisponibles(): Promise<Array<{
    id: string;
    nom: string;
    description: string;
    formatsSupportes: FormatExport[];
    sections: string[];
  }>> {
    try {
      const response = await ApiService.get<Array<{
        id: string;
        nom: string;
        description: string;
        formatsSupportes: FormatExport[];
        sections: string[];
      }>>('/calculs-techniques/templates-export');

      return response;

    } catch (error) {
      // Templates par défaut
      return [
        {
          id: 'STANDARD',
          nom: 'Standard',
          description: 'Export standard avec informations essentielles',
          formatsSupportes: ['CSV', 'EXCEL', 'PDF'],
          sections: ['donnees_base']
        },
        {
          id: 'DETAILLE',
          nom: 'Détaillé',
          description: 'Export complet avec toutes les spécifications techniques',
          formatsSupportes: ['EXCEL', 'PDF'],
          sections: ['donnees_base', 'specifications', 'calculs', 'normes']
        },
        {
          id: 'RESUME',
          nom: 'Résumé',
          description: 'Export synthétique pour présentation',
          formatsSupportes: ['PDF'],
          sections: ['resume', 'graphiques']
        }
      ];
    }
  }

  /**
   * Validation des options d'export
   */
  static validerOptionsExport(options: OptionsExport): {
    valide: boolean;
    erreurs: string[];
  } {
    const erreurs: string[] = [];

    if (!options.format) {
      erreurs.push('Format d\'export requis');
    }

    if (options.format === 'PDF' && options.colonnesPersonnalisees?.length > 20) {
      erreurs.push('Maximum 20 colonnes pour export PDF');
    }

    if (options.includeImages && options.format === 'CSV') {
      erreurs.push('Images non supportées en format CSV');
    }

    return {
      valide: erreurs.length === 0,
      erreurs
    };
  }

  // =================== MÉTHODES PRIVÉES ===================

  /**
   * Génère un nom de fichier unique
   */
  private static genererNomFichier(prefix: string, format: FormatExport): string {
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
    const extension = format.toLowerCase();
    return `${prefix}_${timestamp}.${extension}`;
  }

  /**
   * Export côté client en cas de problème serveur
   */
  private static async exporterCalculsCoteClient(
    calculs: any[],
    options: OptionsExport
  ): Promise<ResultatExport> {
    let contenu = '';
    
    if (options.format === 'CSV') {
      // Génération CSV simple
      contenu = 'Type,Résultat,Date\n';
      calculs.forEach(calcul => {
        contenu += `${calcul.type},"${JSON.stringify(calcul.resultat)}",${new Date().toISOString()}\n`;
      });
    } else {
      // Format texte pour autres formats
      contenu = 'Export des calculs techniques BTP\n\n';
      calculs.forEach(calcul => {
        contenu += `Type: ${calcul.type}\n`;
        contenu += `Résultat: ${JSON.stringify(calcul.resultat, null, 2)}\n\n`;
      });
    }

    const blob = new Blob([contenu], { type: 'text/plain;charset=utf-8' });
    const filename = this.genererNomFichier('calculs-fallback', 'CSV');

    return {
      filename,
      blob,
      size: blob.size,
      format: 'CSV',
      nbLignes: calculs.length,
      dateGeneration: new Date().toISOString()
    };
  }
}