# 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():
    generator = AtomicGraphGenerator()
    generator.run()
    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']
    if  configuracion['training']: 
        processor = TrainingProcessor()
        processor.run()

    

    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}")

    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()


    #BT clasificator test
    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', 'group']])
    



#####CLASIFICACION DE DEFECTOS



    classifier = VacancyClassifier(
        json_file1='outputs/json/training_data.json',
        json_file2='outputs/json/training_graph.json',
        merged_json='outputs/json/merged_training.json',
        csv_input='outputs/csv/defect_data.csv',
        csv_output='outputs/csv/defect_data_classified.csv'
    )
    classifier.merge_json()
    classifier.train()
    classifier.classify_defects()



















    # 8. Predicción con modelos
    params = cargar_json_usuario()













    predictor_cols = params.get("PREDICTOR_COLUMNS", None)
    if predictor_cols is None or not isinstance(predictor_cols, list) or len(predictor_cols) == 0:
        raise KeyError("input_params.json debe contener 'PREDICTOR_COLUMNS' (lista no vacía) en el nivel raíz.")

    rf_predictor = VacancyPredictorRF(
        json_path="outputs/json/training_data.json",
        predictor_columns=predictor_cols
    )
    xgb_predictor = XGBoostVacancyPredictor(
        training_data_path="outputs/json/training_data.json",
        model_path="outputs/json/xgboost_model.json",
        predictor_columns=predictor_cols
    )
    rf_predictor_graph = VacancyPredictorRF(
        json_path="outputs/json/training_graph.json",
        predictor_columns=predictor_cols
    )
    xgb_predictor_graph = XGBoostVacancyPredictor(
        training_data_path="outputs/json/training_graph.json",
        model_path="outputs/json/xgboost_model.json",
        predictor_columns=predictor_cols
    )

    csv_path = os.path.join("outputs", "csv", "defect_data.csv")
    if not os.path.isfile(csv_path):
        raise FileNotFoundError(f"No se encontró el CSV en: {csv_path}")

    df = pd.read_csv(csv_path)

    

    winner_finder = WinnerFinger(
        defect_csv=Path("outputs/csv/finger_defect_data.csv"),
        normal_csv=Path("outputs/csv/finger_data.csv"),
        output_csv=Path("outputs/csv/finger_winner_data.csv"),
        id_col="file_name"
    )
    winner_finder.run()

    defect_csv = Path('outputs/csv/defect_data.csv')
    finger_csv = Path('outputs/csv/finger_winner_data.csv')
    output_csv = Path('outputs/csv/defect_data.csv')

    defect_df = pd.read_csv(defect_csv)
    finger_df = pd.read_csv(finger_csv)
    finger_df = finger_df[['defect_file', 'fingerprint']]
    defect_df['file_name'] = defect_df['archivo'].apply(lambda p: Path(p).name)

    enriched = defect_df.merge(
        finger_df,
        how='left',
        left_on='file_name',
        right_on='defect_file'
    )

    enriched = enriched.drop(columns=['file_name', 'defect_file'])
    enriched.to_csv(output_csv, index=False)
    print(f'CSV enriquecido guardado en: {output_csv}')

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



