import { useState, useEffect, useCallback } from 'react';
import { 
  MaterielBTPService, 
  MaterielBTP, 
  CategorieMateriel, 
  RechercheMaterielParams 
} from '../services/materielBTPService';
import { 
  ZoneClimatiqueService, 
  ZoneClimatique, 
  CriteresRecherche 
} from '../services/zoneClimatiqueService';
import { 
  CalculsTechniquesService,
  ParametresCalculBriques,
  ResultatCalculBriques,
  ParametresCalculBetonArme,
  ResultatCalculBetonArme
} from '../services/calculsTechniquesService';
import { 
  ExportBTPService, 
  FormatExport, 
  OptionsExport, 
  ResultatExport 
} from '../services/exportBTPService';

/**
 * Hook personnalisé pour l'utilisation des services BTP ultra-détaillés
 * Système le plus ambitieux d'Afrique pour la gestion BTP
 */

export interface UseBTPServicesReturn {
  // États de chargement
  loading: {
    materiaux: boolean;
    zones: boolean;
    calculs: boolean;
    export: boolean;
  };

  // États d'erreur
  errors: {
    materiaux: string | null;
    zones: string | null;
    calculs: string | null;
    export: string | null;
  };

  // Données
  data: {
    materiaux: MaterielBTP[];
    zones: ZoneClimatique[];
    dernierCalcul: any;
    dernierExport: ResultatExport | null;
  };

  // Actions matériaux
  materiaux: {
    charger: (params?: RechercheMaterielParams) => Promise<void>;
    rechercher: (criteres: RechercheMaterielParams) => Promise<MaterielBTP[]>;
    obtenirParCode: (code: string) => Promise<MaterielBTP>;
    obtenirParCategorie: (categorie: CategorieMateriel) => Promise<MaterielBTP[]>;
    validerPourZone: (codeMateriel: string, zoneCode: string) => Promise<any>;
    obtenirAlternatives: (codeMateriel: string, zoneCode?: string) => Promise<MaterielBTP[]>;
  };

  // Actions zones climatiques
  zones: {
    charger: () => Promise<void>;
    rechercher: (criteres: CriteresRecherche) => Promise<ZoneClimatique[]>;
    obtenirParCode: (code: string) => Promise<ZoneClimatique>;
    obtenirMeilleureAdaptation: (temp: number, humidite: number, vents: number) => Promise<ZoneClimatique | null>;
    obtenirRecommandations: (zoneCode: string) => Promise<any>;
    simulerImpact: (zoneCode: string, parametres: any) => Promise<any>;
  };

  // Actions calculs techniques
  calculs: {
    calculerBriques: (params: ParametresCalculBriques) => Promise<ResultatCalculBriques>;
    calculerBetonArme: (params: ParametresCalculBetonArme) => Promise<ResultatCalculBetonArme>;
    obtenirDosagesBeton: () => Promise<any>;
    estimationRapideBriques: (surface: number, typeBrique?: string) => Promise<any>;
    estimationRapideBeton: (volume: number, classeBeton?: string) => Promise<any>;
    genererDevis: (calculs: any, options?: any) => Promise<any>;
  };

  // Actions export
  export: {
    exporterMateriaux: (options: OptionsExport & { filtres?: RechercheMaterielParams }) => Promise<void>;
    exporterZones: (options: OptionsExport) => Promise<void>;
    exporterCalculs: (calculs: any[], options: OptionsExport) => Promise<void>;
    genererDevis: (devisData: any, format?: FormatExport) => Promise<void>;
    telechargerDernier: () => void;
  };

  // Utilitaires
  utils: {
    reinitialiser: () => void;
    obtenirStatistiques: () => any;
    validerParametres: (type: string, params: any) => any;
  };
}

export const useBTPServices = (): UseBTPServicesReturn => {
  // États de chargement
  const [loading, setLoading] = useState({
    materiaux: false,
    zones: false,
    calculs: false,
    export: false
  });

  // États d'erreur
  const [errors, setErrors] = useState({
    materiaux: null as string | null,
    zones: null as string | null,
    calculs: null as string | null,
    export: null as string | null
  });

  // Données
  const [data, setData] = useState({
    materiaux: [] as MaterielBTP[],
    zones: [] as ZoneClimatique[],
    dernierCalcul: null as any,
    dernierExport: null as ResultatExport | null
  });

  // =================== FONCTIONS UTILITAIRES ===================

  const setLoadingState = useCallback((key: keyof typeof loading, value: boolean) => {
    setLoading(prev => ({ ...prev, [key]: value }));
  }, []);

  const setErrorState = useCallback((key: keyof typeof errors, error: string | null) => {
    setErrors(prev => ({ ...prev, [key]: error }));
  }, []);

  const handleError = useCallback((key: keyof typeof errors, error: any) => {
    const message = error?.message || error?.toString() || 'Une erreur est survenue';
    setErrorState(key, message);
    console.error(`Erreur ${key}:`, error);
  }, [setErrorState]);

  // =================== ACTIONS MATÉRIAUX ===================

  const chargerMateriaux = useCallback(async (params?: RechercheMaterielParams) => {
    setLoadingState('materiaux', true);
    setErrorState('materiaux', null);

    try {
      const response = await MaterielBTPService.getMateriaux(params);
      setData(prev => ({ ...prev, materiaux: response.materiaux }));
    } catch (error) {
      handleError('materiaux', error);
    } finally {
      setLoadingState('materiaux', false);
    }
  }, [setLoadingState, setErrorState, handleError]);

  const rechercherMateriaux = useCallback(async (criteres: RechercheMaterielParams): Promise<MaterielBTP[]> => {
    try {
      return await MaterielBTPService.rechercherMateriaux(criteres);
    } catch (error) {
      handleError('materiaux', error);
      return [];
    }
  }, [handleError]);

  const obtenirMaterielParCode = useCallback(async (code: string): Promise<MaterielBTP> => {
    try {
      return await MaterielBTPService.getMaterielByCode(code);
    } catch (error) {
      handleError('materiaux', error);
      throw error;
    }
  }, [handleError]);

  const obtenirMateriauxParCategorie = useCallback(async (categorie: CategorieMateriel): Promise<MaterielBTP[]> => {
    try {
      return await MaterielBTPService.getMateriauxByCategorie(categorie);
    } catch (error) {
      handleError('materiaux', error);
      return [];
    }
  }, [handleError]);

  const validerMaterielPourZone = useCallback(async (codeMateriel: string, zoneCode: string) => {
    try {
      return await MaterielBTPService.validerMaterielPourZone(codeMateriel, zoneCode);
    } catch (error) {
      handleError('materiaux', error);
      return { adapte: false, warnings: ['Validation impossible'], recommendations: [] };
    }
  }, [handleError]);

  const obtenirAlternativesMateriel = useCallback(async (codeMateriel: string, zoneCode?: string): Promise<MaterielBTP[]> => {
    try {
      return await MaterielBTPService.getAlternativesMateriel(codeMateriel, zoneCode);
    } catch (error) {
      handleError('materiaux', error);
      return [];
    }
  }, [handleError]);

  // =================== ACTIONS ZONES CLIMATIQUES ===================

  const chargerZones = useCallback(async () => {
    setLoadingState('zones', true);
    setErrorState('zones', null);

    try {
      const response = await ZoneClimatiqueService.getZonesClimatiques();
      setData(prev => ({ ...prev, zones: response.zones }));
    } catch (error) {
      handleError('zones', error);
    } finally {
      setLoadingState('zones', false);
    }
  }, [setLoadingState, setErrorState, handleError]);

  const rechercherZones = useCallback(async (criteres: CriteresRecherche): Promise<ZoneClimatique[]> => {
    try {
      return await ZoneClimatiqueService.rechercherZones(criteres);
    } catch (error) {
      handleError('zones', error);
      return [];
    }
  }, [handleError]);

  const obtenirZoneParCode = useCallback(async (code: string): Promise<ZoneClimatique> => {
    try {
      return await ZoneClimatiqueService.getZoneByCode(code);
    } catch (error) {
      handleError('zones', error);
      throw error;
    }
  }, [handleError]);

  const obtenirMeilleureAdaptation = useCallback(async (temp: number, humidite: number, vents: number) => {
    try {
      return await ZoneClimatiqueService.getMeilleureAdaptation(temp, humidite, vents);
    } catch (error) {
      handleError('zones', error);
      return null;
    }
  }, [handleError]);

  const obtenirRecommandationsZone = useCallback(async (zoneCode: string) => {
    try {
      return await ZoneClimatiqueService.getRecommandationsConstruction(zoneCode);
    } catch (error) {
      handleError('zones', error);
      return { fondations: [], structure: [], enveloppe: [], finitions: [], equipements: [] };
    }
  }, [handleError]);

  const simulerImpactClimatique = useCallback(async (zoneCode: string, parametres: any) => {
    try {
      return await ZoneClimatiqueService.simulerImpactClimatique(zoneCode, parametres);
    } catch (error) {
      handleError('zones', error);
      return null;
    }
  }, [handleError]);

  // =================== ACTIONS CALCULS TECHNIQUES ===================

  const calculerBriquesMur = useCallback(async (params: ParametresCalculBriques): Promise<ResultatCalculBriques> => {
    setLoadingState('calculs', true);
    setErrorState('calculs', null);

    try {
      const resultat = await CalculsTechniquesService.calculerBriquesMur(params);
      setData(prev => ({ ...prev, dernierCalcul: { type: 'BRIQUES', resultat, params } }));
      return resultat;
    } catch (error) {
      handleError('calculs', error);
      throw error;
    } finally {
      setLoadingState('calculs', false);
    }
  }, [setLoadingState, setErrorState, handleError]);

  const calculerBetonArme = useCallback(async (params: ParametresCalculBetonArme): Promise<ResultatCalculBetonArme> => {
    setLoadingState('calculs', true);
    setErrorState('calculs', null);

    try {
      const resultat = await CalculsTechniquesService.calculerBetonArme(params);
      setData(prev => ({ ...prev, dernierCalcul: { type: 'BETON', resultat, params } }));
      return resultat;
    } catch (error) {
      handleError('calculs', error);
      throw error;
    } finally {
      setLoadingState('calculs', false);
    }
  }, [setLoadingState, setErrorState, handleError]);

  const obtenirDosagesBeton = useCallback(async () => {
    try {
      return await CalculsTechniquesService.getDosagesBeton();
    } catch (error) {
      handleError('calculs', error);
      return { dosages: {}, notes: [] };
    }
  }, [handleError]);

  const estimationRapideBriques = useCallback(async (surface: number, typeBrique?: string) => {
    try {
      return await CalculsTechniquesService.estimationRapideBriques(surface, typeBrique);
    } catch (error) {
      handleError('calculs', error);
      return { estimationBasse: 0, estimationHaute: 0, estimationMoyenne: 0, baseCalcul: '' };
    }
  }, [handleError]);

  const estimationRapideBeton = useCallback(async (volume: number, classeBeton?: string) => {
    try {
      return await CalculsTechniquesService.estimationRapideBeton(volume, classeBeton);
    } catch (error) {
      handleError('calculs', error);
      return { cimentSacs: 0, sableM3: 0, graviersM3: 0, eauLitres: 0, coutEstime: 0 };
    }
  }, [handleError]);

  const genererDevis = useCallback(async (calculs: any, options?: any) => {
    try {
      return await CalculsTechniquesService.genererDevis(calculs, options);
    } catch (error) {
      handleError('calculs', error);
      return { lignesDevis: [], totalHT: 0, totalTTC: 0, delaiExecution: 0 };
    }
  }, [handleError]);

  // =================== ACTIONS EXPORT ===================

  const exporterMateriaux = useCallback(async (options: OptionsExport & { filtres?: RechercheMaterielParams }) => {
    setLoadingState('export', true);
    setErrorState('export', null);

    try {
      const resultat = await ExportBTPService.exporterMateriaux(options);
      setData(prev => ({ ...prev, dernierExport: resultat }));
      ExportBTPService.telechargerFichier(resultat);
    } catch (error) {
      handleError('export', error);
    } finally {
      setLoadingState('export', false);
    }
  }, [setLoadingState, setErrorState, handleError]);

  const exporterZones = useCallback(async (options: OptionsExport) => {
    setLoadingState('export', true);
    setErrorState('export', null);

    try {
      const resultat = await ExportBTPService.exporterZonesClimatiques(options);
      setData(prev => ({ ...prev, dernierExport: resultat }));
      ExportBTPService.telechargerFichier(resultat);
    } catch (error) {
      handleError('export', error);
    } finally {
      setLoadingState('export', false);
    }
  }, [setLoadingState, setErrorState, handleError]);

  const exporterCalculs = useCallback(async (calculs: any[], options: OptionsExport) => {
    setLoadingState('export', true);
    setErrorState('export', null);

    try {
      const resultat = await ExportBTPService.exporterCalculs(calculs, options);
      setData(prev => ({ ...prev, dernierExport: resultat }));
      ExportBTPService.telechargerFichier(resultat);
    } catch (error) {
      handleError('export', error);
    } finally {
      setLoadingState('export', false);
    }
  }, [setLoadingState, setErrorState, handleError]);

  const genererDevisBTP = useCallback(async (devisData: any, format: FormatExport = 'PDF') => {
    setLoadingState('export', true);
    setErrorState('export', null);

    try {
      const resultat = await ExportBTPService.genererDevisBTP(devisData, format);
      setData(prev => ({ ...prev, dernierExport: resultat }));
      ExportBTPService.telechargerFichier(resultat);
    } catch (error) {
      handleError('export', error);
    } finally {
      setLoadingState('export', false);
    }
  }, [setLoadingState, setErrorState, handleError]);

  const telechargerDernierExport = useCallback(() => {
    if (data.dernierExport) {
      ExportBTPService.telechargerFichier(data.dernierExport);
    }
  }, [data.dernierExport]);

  // =================== UTILITAIRES ===================

  const reinitialiser = useCallback(() => {
    setData({
      materiaux: [],
      zones: [],
      dernierCalcul: null,
      dernierExport: null
    });
    setErrors({
      materiaux: null,
      zones: null,
      calculs: null,
      export: null
    });
  }, []);

  const obtenirStatistiques = useCallback(() => {
    return {
      nbMateriaux: data.materiaux.length,
      nbZones: data.zones.length,
      categoriesMateriaux: [...new Set(data.materiaux.map(m => m.categorie))],
      derniereActivite: data.dernierCalcul ? new Date(data.dernierCalcul.date || Date.now()) : null,
      tailleDernierExport: data.dernierExport?.size || 0
    };
  }, [data]);

  const validerParametres = useCallback((type: string, params: any) => {
    return CalculsTechniquesService.validerParametres(type as any, params);
  }, []);

  // =================== CHARGEMENT INITIAL ===================

  useEffect(() => {
    // Chargement automatique des données de base
    chargerZones();
  }, [chargerZones]);

  // =================== RETURN ===================

  return {
    loading,
    errors,
    data,
    
    materiaux: {
      charger: chargerMateriaux,
      rechercher: rechercherMateriaux,
      obtenirParCode: obtenirMaterielParCode,
      obtenirParCategorie: obtenirMateriauxParCategorie,
      validerPourZone: validerMaterielPourZone,
      obtenirAlternatives: obtenirAlternativesMateriel
    },

    zones: {
      charger: chargerZones,
      rechercher: rechercherZones,
      obtenirParCode: obtenirZoneParCode,
      obtenirMeilleureAdaptation,
      obtenirRecommandations: obtenirRecommandationsZone,
      simulerImpact: simulerImpactClimatique
    },

    calculs: {
      calculerBriques: calculerBriquesMur,
      calculerBetonArme,
      obtenirDosagesBeton,
      estimationRapideBriques,
      estimationRapideBeton,
      genererDevis
    },

    export: {
      exporterMateriaux,
      exporterZones,
      exporterCalculs,
      genererDevis: genererDevisBTP,
      telechargerDernier: telechargerDernierExport
    },

    utils: {
      reinitialiser,
      obtenirStatistiques,
      validerParametres
    }
  };
};