# main.py

from .core import *  
from .config_loader import cargar_json_usuario
from pathlib import Path
import os
import pandas as pd
import warnings
warnings.filterwarnings('ignore', message='.*OVITO.*PyPI')

def VacancyAnalysis():
    
    base = "outputs"
    for sub in ("csv", "dump", "json"):
        os.makedirs(os.path.join(base, sub), exist_ok=True)

    


    
    CONFIG = cargar_json_usuario()
    
    if "CONFIG" not in CONFIG or not isinstance(CONFIG["CONFIG"], list) or len(CONFIG["CONFIG"]) == 0:
        raise ValueError("input_params.json debe contener una lista 'CONFIG' con al menos un objeto.")

    configuracion = CONFIG["CONFIG"][0]
    defect_file = configuracion['defect']

    cs_out_dir = Path("inputs")
    cs_generator = CrystalStructureGenerator(configuracion, cs_out_dir)
    dump_path = cs_generator.generate()
    #print(f"Estructura relajada generada en: {dump_path}")
    if configuracion['training']:
        gen = AtomicGraphGenerator()
        gen.run()




        
    processor = ClusterProcessor(defect_file)
    processor.run()
    separator = KeyFilesSeparator(configuracion, os.path.join("outputs/json", "clusters.json"))
    separator.run()

    # 3. Procesar dumps críticos
    clave_criticos = ClusterDumpProcessor.cargar_lista_archivos_criticos("outputs/json/key_archivos.json")
    for archivo in clave_criticos:
        try:
            dump_proc = ClusterDumpProcessor(archivo, decimals=5)
            dump_proc.load_data()
            dump_proc.process_clusters()
            dump_proc.export_updated_file(f"{archivo}_actualizado.txt")
        except Exception as e:
            print(f"Error procesando {archivo}: {e}")

    # 4. Subdivisión iterativa
    lista_criticos = ClusterDumpProcessor.cargar_lista_archivos_criticos("outputs/json/key_archivos.json")
    for archivo in lista_criticos:
        machine_proc = ClusterProcessorMachine(archivo, configuracion['cluster tolerance'], configuracion['iteraciones_clusterig'])
        machine_proc.process_clusters()
        machine_proc.export_updated_file()

    # 5. Separar archivos finales vs críticos
    separator = KeyFilesSeparator(configuracion, os.path.join("outputs/json", "clusters.json"))
    separator.run()

    # 6. Generar nuevos dumps por cluster
    export_list = ExportClusterList("outputs/json/key_archivos.json")
    export_list.process_files()

    # 7. Calcular superficies de dump
    surf_proc = SurfaceProcessor(configuracion)
    surf_proc.process_all_files()
    surf_proc.export_results()



    exporter = ClusterFeatureExporter("outputs/json/key_archivos.json")
    exporter.export()


    # ------------------------------------------------------------------------
    # 8. Entrenar y clasificar defectos con el nuevo modelo ensemble

    # Instancia y entrena el modelo
    clf = ImprovedVacancyClassifier(json_path='outputs/json/training_graph.json')
    clf.train()  
    # → ya imprime mejores parámetros y reporte de clasificación

    # Clasifica tu CSV de defectos (añade columna 'grupo_predicho')
    df_clasif = clf.classify_csv(
        csv_path='outputs/csv/defect_data.csv',
        output_path='outputs/csv/finger_data_clasificado.csv'
    )
    print(df_clasif[['archivo','grupo_predicho']])
    # ------------------------------------------------------------------------
    # 9. Predicción de vacancias según grupo_predicho
    # Como ImprovedVacancyClassifier usa la misma API de train/classify,
    # podemos reusar el método classify_csv para predecir vacancias
    # (o bien, si lo prefieres, crear un método predict_from_csv
    #  similar al anterior)
    df_pred = clf.classify_csv(
        csv_path='outputs/csv/finger_data_clasificado.csv',
        output_path='outputs/csv/finger_data_predicha.csv'
    )
    print("✅ Vacancias predichas guardadas en outputs/csv/finger_data_predicha.csv")

    # ------------------------------------------------------------------------
    # 10. Continuar con el resto de tu pipeline
    assigner = FingerprintVacancyAssigner(
        base_csv_path="outputs/csv/finger_data.csv",
        query_csv_path="outputs/csv/finger_key_files.csv",
        weight_N=1
    )
    df_result = assigner.assign()
    df_result.to_csv("outputs/csv/finger_key_files_clasificado.csv", index=False)
    print("✅ Resultado guardado con peso_N =", assigner.weight_N)
    #Calcular categoria de defect_file.csv
    #model = BehaviorTreeModel(weight_cluster_size=2.0, max_depth=5)
    #model.train('outputs/json/training_graph.json')

    #df_resultado = model.classify_csv(
     #   csv_path='outputs/csv/defect_data.csv',
      #  output_path='outputs/csv/finger_data_clasificado.csv'
    #)

    #print(df_resultado[['archivo', 'grupo_predicho']])


    #ETAPA DE PREDICCIONES


    trainer = VacancyModelTrainer(json_path='outputs/json/training_graph.json')
    trainer.load_data()
    trainer.train_all_models()
    #
    #  Predecir en lote desde archivo CSV
    # Supongamos que en la etapa anterior guardaste:
    # outputs/csv/finger_data_clasificado.csv
    df_pred = trainer.predict_from_csv('outputs/csv/finger_data_clasificado.csv')
    df_pred.to_csv('outputs/csv/finger_data_predicha.csv', index=False)
    print("✅ Vacancias predichas guardadas en outputs/csv/finger_data_predicha.csv")

# Ejemplo de uso
    assigner = FingerprintVacancyAssigner(
        base_csv_path="outputs/csv/finger_data.csv",
        query_csv_path="outputs/csv/finger_key_files.csv",
        weight_N=.5 # peso mayor para 'N'
    )
    df_result = assigner.assign()
    df_result.to_csv("outputs/csv/finger_key_files_clasificado.csv", index=False)
    print("✅ Resultado guardado con peso_N =", assigner.weight_N)

if __name__ == "__main__":
    VacancyAnalysis()
    print("Script ejecutado correctamente.")



