import math
from typing import Dict

import matplotlib.pyplot as plt
import numpy as np
from pandas import DataFrame
from sklearn import cluster, metrics


def get_best_clusters_num(
    X: DataFrame, random_state: int, max_clusters: int | None = None
) -> Dict[int, float]:
    max_clusters = int(math.sqrt(len(X)) + 0.5) + 1
    silhouette_scores: Dict[int, float] = {}
    for cluster_num in range(2, max_clusters + 1):
        kmeans = cluster.KMeans(n_clusters=cluster_num, random_state=random_state)
        labels = kmeans.fit_predict(X)
        silhouette_scores[cluster_num] = float(metrics.silhouette_score(X, labels))

    return silhouette_scores


def draw_best_clusters_plot(clusters_score: Dict[int, float]):
    plt.figure(figsize=(4, 4))
    plt.plot(list(clusters_score.keys()), list(clusters_score.values()), "bo-")
    plt.xlabel("Clusters count", fontsize=8)
    plt.ylabel("Silhouette score", fontsize=8)
    plt.title("The Silhouette score")
    plt.show()


def print_cluster_result(X: DataFrame, clusters_num: int, labels: np.ndarray):
    for cluster_id in range(clusters_num):
        cluster_indices = np.where(labels == cluster_id)[0]
        print(f"Кластер {cluster_id + 1} ({len(cluster_indices)}):")
        rules = [str(X.index[idx]) for idx in cluster_indices]
        print(";\n".join(rules))
        print("--------")
