import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.cluster import KMeans
from sklearn.metrics import (
    silhouette_score, adjusted_rand_score, normalized_mutual_info_score
)
from sklearn.decomposition import PCA


# 1) f[^ǂݍ & W
wine = load_wine()
X, y = wine.data, wine.target

scaler = StandardScaler()
X_std = scaler.fit_transform(X)


# 2) kς inertia / silhouette vZ
ks = range(2, 8 + 1)
inertias, silhouettes = [], []
for k in ks:
    km = KMeans(n_clusters=k,
                n_init=20, random_state=42, init="k-means++")
    labels = km.fit_predict(X_std)
    inertias.append(km.inertia_)
    silhouettes.append(silhouette_score(X_std, labels))
print(pd.DataFrame({"k": ks,
      "inertia": inertias, "silhouette": silhouettes}))

# FG{[}
plt.figure()
plt.title("Elbow Method (Inertia) on Wine")
plt.plot(list(ks), inertias, marker="o")
plt.xlabel("k"); plt.ylabel("Inertia")
plt.tight_layout()
plt.show()

# FVGbgW
plt.figure()
plt.title("Silhouette Score vs k (Wine)")
plt.plot(list(ks), silhouettes, marker="s")
plt.xlabel("k"); plt.ylabel("Silhouette Score")
plt.tight_layout()
plt.show()


# 3) VGbgők̗p
best_k = int(ks[np.argmax(silhouettes)])
print(f"Chosen k (by silhouette max): {best_k}")


# ̗p k ōŏIfwK
kmeans = KMeans(n_clusters=best_k, n_init=20,
                random_state=42, init="k-means++")
labels = kmeans.fit_predict(X_std)


# 4) PCA
pca = PCA(n_components=2, random_state=42)
X_pca = pca.fit_transform(X_std)

markers = ["o", "s", "^", "D", "x", "*", "P", "X"]  # LZbg

# (a) \NX^
plt.figure()
plt.title(f"KMeans Clusters (k={best_k})")
for cid in np.unique(labels):
    plt.scatter(
        X_pca[labels == cid, 0],
        X_pca[labels == cid, 1],
        marker=markers[cid % len(markers)],
        edgecolor="k",
        linewidths=0.2,
        label=f"Cluster {cid}"
    )
plt.xlabel("PC1"); plt.ylabel("PC2")
plt.legend()
plt.tight_layout()
plt.show()

# (b) QlF^̃x
plt.figure()
plt.title("True Classes (Reference)")
for cls in np.unique(y):
    plt.scatter(
        X_pca[y == cls, 0],
        X_pca[y == cls, 1],
        marker=markers[cls],
        edgecolor="k",
        linewidths=0.2,
        label=wine.target_names[cls]
    )
plt.xlabel("PC1"); plt.ylabel("PC2")
plt.legend()
plt.tight_layout()
plt.show()