import pandas as pd
import numpy as np

def fix_kmedoids_greedy(fichier_csv, fichier_matrice, fichier_sortie="k_medoids_fixed_greedy.csv"):
    print("Chargement des données...")
    df = pd.read_csv(fichier_csv)
    matrice_dist = np.load(fichier_matrice)
    n_total_points = matrice_dist.shape[0]

    df = df.sort_values(by='k').reset_index(drop=True)
    corrections = 0

    for i in range(1, len(df)):
        cout_prec = df.at[i-1, 'cout_F_k*']
        cout_actuel = df.at[i, 'cout_F_k*']

        if cout_actuel > cout_prec:
            f_k_prec_str = str(df.at[i-1, 'F_k*'])
            f_k_prec_list = [int(x) for x in f_k_prec_str.split(';')]
            
            # Distances actuelles avec F_{k-1}
            dist_actuelles = np.min(matrice_dist[:, f_k_prec_list], axis=1)

            meilleur_point = -1
            meilleur_cout = float('inf')

            # On teste tous les points qui ne sont pas encore dans F_{k-1}
            points_a_tester = np.setdiff1d(np.arange(n_total_points), f_k_prec_list)
            
            # Optimisation NumPy : on teste tous les ajouts d'un coup
            # matrice_dist[:, points_a_tester] contient les distances vers tous les candidats
            # np.minimum compare chaque colonne candidate avec les distances actuelles
            nouvelles_distances = np.minimum(dist_actuelles[:, None], matrice_dist[:, points_a_tester])
            
            # On somme chaque colonne pour avoir le coût total pour chaque candidat
            couts_candidats = np.sum(nouvelles_distances, axis=0)
            
            # On trouve l'indice du meilleur candidat
            idx_meilleur = np.argmin(couts_candidats)
            meilleur_point = points_a_tester[idx_meilleur]
            nouveau_cout = couts_candidats[idx_meilleur]

            # Mise à jour du DataFrame
            nouveau_f_k = f_k_prec_list + [meilleur_point]
            df.at[i, 'cout_F_k*'] = nouveau_cout
            df.at[i, 'F_k*'] = ";".join(map(str, nouveau_f_k))
            df.at[i, 'temps_calcul_s'] = 0.0
            
            corrections += 1
            print(f"k={df.at[i, 'k']} corrigé (Greedy) | Coût: {cout_actuel:.0f} -> {nouveau_cout:.0f} (Ajout du point {meilleur_point})")

    df.to_csv(fichier_sortie, index=False)
    print(f"Terminé ! {corrections} corrections (méthode Greedy) appliquées. Sauvegardé dans {fichier_sortie}.")

# Utilisation :
path_opt = "/Users/imrane/Downloads/application/sym/sym_data/resultats_kmedoids.csv"
path_matrice = "/Users/imrane/Downloads/application/sym/sym_data/matrice_distances.npy"
fix_kmedoids_greedy(path_opt, path_matrice)