import pandas as pd

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, confusion_matrix

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Input, Dense

# 1. LOAD DATASET

df = pd.read_csv("Churn_Modelling(2).csv")

print(df.head())
print("Columns:", df.columns)
print("Missing Values:\n", df.isnull().sum())
print("Target Distribution:\n", df["Exited"].value_counts())

# 2. FEATURES AND TARGET

features = ["CreditScore", "Geography", "Gender", "Age",
            "Tenure", "Balance", "NumOfProducts",
            "HasCrCard", "IsActiveMember", "EstimatedSalary"]

df = df.dropna(subset=features + ["Exited"])

X = df[features]
y = df["Exited"]

# 3. ENCODE CATEGORICAL FEATURES

# Encode categories after splitting so only training columns define the schema.

# 4. TRAIN-TEST SPLIT

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# Learn category choices from training rows only (also keeps dropped baselines consistent).
for column in X_train.select_dtypes(include=["object", "string", "category"]):
    categories = X_train[column].dropna().unique()
    X_train[column] = pd.Categorical(X_train[column], categories=categories)
    X_test[column] = pd.Categorical(X_test[column], categories=categories)
# Match test columns to training columns; unseen categories become zero.
X_train = pd.get_dummies(X_train, drop_first=False, dtype=int)
X_test = pd.get_dummies(X_test, drop_first=False, dtype=int).reindex(columns=X_train.columns, fill_value=0)


# SCALE USING TRAINING DATA

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# 5. BUILD ANN

model = Sequential([
    Input(shape=(X_train.shape[1],)),
    Dense(16, activation="relu"),
    Dense(8, activation="relu"),
    Dense(1, activation="sigmoid")
])

# 6. COMPILE AND TRAIN

model.compile(optimizer="adam",
              loss="binary_crossentropy",
              metrics=["accuracy"])

model.fit(X_train, y_train, epochs=20, batch_size=32)

# 7. PREDICT AND EVALUATE

y_pred = (model.predict(X_test) > 0.5).astype(int).ravel()

print("Accuracy:", accuracy_score(y_test, y_pred))
print("Confusion Matrix:\n", confusion_matrix(y_test, y_pred))


# ENHANCED: Training churn-label distribution
import matplotlib.pyplot as plt
y_train.value_counts().sort_index().plot(kind="bar")
plt.ylabel("Training customers")
plt.title("Training Churn Distribution")
plt.show()
