import warnings

import matplotlib.pyplot as plt
import pandas as pd
from sklearn.ensemble import GradientBoostingClassifier, RandomForestClassifier
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.svm import SVC

warnings.filterwarnings("ignore")

DATA_URL = "https://autotrain.app/opendata92bd.html?file=ObesityDataSet_raw_and_data_sinthetic.csv"

df = pd.read_csv(DATA_URL)
target_col = "NObeyesdad" if "NObeyesdad" in df.columns else df.columns[-1]

X = df.drop(columns=[target_col])
y = df[target_col]

X_encoded = X.copy()
for col in X_encoded.columns:
    if X_encoded[col].dtype == "object":
        encoder = LabelEncoder()
        X_encoded[col] = encoder.fit_transform(X_encoded[col].astype(str))

target_encoder = LabelEncoder()
y_encoded = target_encoder.fit_transform(y.astype(str))

X_train, X_test, y_train, y_test = train_test_split(
    X_encoded,
    y_encoded,
    test_size=0.2,
    random_state=42,
    stratify=y_encoded,
)

models = {
    "Random Forest": RandomForestClassifier(
        n_estimators=200,
        random_state=42,
        class_weight="balanced",
    ),
    "Gradient Boosting": GradientBoostingClassifier(random_state=42),
    "SVM": Pipeline(
        [
            ("scaler", StandardScaler()),
            ("model", SVC(kernel="rbf", probability=True, random_state=42)),
        ]
    ),
    "KNN": Pipeline(
        [
            ("scaler", StandardScaler()),
            ("model", KNeighborsClassifier(n_neighbors=5)),
        ]
    ),
}

results = []
for name, model in models.items():
    model.fit(X_train, y_train)
    preds = model.predict(X_test)
    results.append(
        {
            "model": name,
            "accuracy": accuracy_score(y_test, preds),
            "precision_macro": precision_score(
                y_test, preds, average="macro", zero_division=0
            ),
            "recall_macro": recall_score(
                y_test, preds, average="macro", zero_division=0
            ),
            "f1_macro": f1_score(y_test, preds, average="macro", zero_division=0),
        }
    )

results_df = pd.DataFrame(results).sort_values("f1_macro", ascending=False)
print(results_df)

rf_model = models["Random Forest"]
rf_model.fit(X_train, y_train)
importance_df = pd.DataFrame(
    {
        "feature": X_encoded.columns,
        "importance": rf_model.feature_importances_,
    }
).sort_values("importance", ascending=False)

top_features = importance_df.head(15).sort_values("importance")
plt.figure(figsize=(8, 6))
plt.barh(top_features["feature"], top_features["importance"])
plt.title("Top 15 Feature Importance - Random Forest")
plt.xlabel("Importance")
plt.tight_layout()
plt.show()

