import streamlit as st
import pandas as pd
import re
import seaborn as sns
import matplotlib.pyplot as plt
# ❌ WordCloud dihapus

from Sastrawi.Stemmer.StemmerFactory import StemmerFactory
from nltk.corpus import stopwords
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
from sklearn.naive_bayes import MultinomialNB

import nltk
nltk.download('stopwords')

st.set_page_config(page_title="Dashboard Sentimen", layout="wide")

# ==============================
# STYLE
# ==============================
st.markdown("""
<style>
html, body {background-color: #ffffff;}
.title {font-size: 32px; font-weight: bold; color: #2c3e50;}
section[data-testid="stSidebar"] {background-color: #f8f9fa;}
.stButton>button {
    background: linear-gradient(90deg, #3498db, #6dd5fa);
    color: white;
    border-radius: 8px;
    border: none;
}
</style>
""", unsafe_allow_html=True)

st.markdown("<div class='title'>📊 Dashboard Analisis Sentimen</div>", unsafe_allow_html=True)
st.markdown("---")

# ==============================
# PREPROCESSING
# ==============================
factory = StemmerFactory()
stemmer = factory.create_stemmer()
stop_words = set(stopwords.words('indonesian'))

def preprocess(text):
    text = re.sub(r'[^a-zA-Z\s]', '', str(text))
    text = text.lower()
    tokens = text.split()
    tokens = [w for w in tokens if w not in stop_words]

    tokens_stem = []
    for w in tokens:
        if len(w) > 4:
            tokens_stem.append(stemmer.stem(w))
        else:
            tokens_stem.append(w)

    return " ".join(tokens_stem)

def label_sentimen(r):
    if r >= 4:
        return "positif"
    elif r == 3:
        return "netral"
    else:
        return "negatif"

# ==============================
# SIDEBAR
# ==============================
st.sidebar.markdown("## 📌 Menu")
menu = st.sidebar.radio(
    "Menu Navigasi",
    ["📂 Upload Data", "🤖 Training", "📊 Evaluasi"],  # ❌ Prediksi dihapus
    label_visibility="collapsed"
)

# ==============================
# UPLOAD
# ==============================
if menu == "📂 Upload Data":

    st.markdown("### 📥 Upload Dataset")
    uploaded = st.file_uploader("Upload file CSV", type=["csv"])

    if uploaded:

        st.info("📊 Sistem sedang memproses dataset...")

        with st.spinner("⏳ Loading & preprocessing data..."):
            progress = st.progress(0)

            df = pd.read_csv(uploaded)
            total_awal = len(df)
            progress.progress(20)

            df = df.dropna(subset=["rating", "ulasan"])
            after_dropna = len(df)
            progress.progress(40)

            df["rating"] = df["rating"].astype(str)
            df["rating"] = df["rating"].str.extract(r'(\d+)')
            df = df[df["rating"].notna()]
            df["rating"] = df["rating"].astype(int)
            progress.progress(60)

            df["sentimen"] = df["rating"].apply(label_sentimen)
            df["clean_text"] = df["ulasan"].apply(preprocess)

            before_clean = len(df)
            df = df[df["clean_text"].str.strip() != ""]
            after_clean = len(df)
            progress.progress(100)

            st.session_state["df"] = df
            st.session_state["total_awal"] = total_awal
            st.session_state["after_dropna"] = after_dropna
            st.session_state["after_clean"] = after_clean

        st.success("✅ Dataset siap!")

    if "df" in st.session_state:

        df = st.session_state["df"]

        st.markdown("### 📊 Statistik Dataset")
        st.write(f"Jumlah awal: {st.session_state['total_awal']}")
        st.write(f"Setelah dropna: {st.session_state['after_dropna']}")
        st.write(f"Setelah preprocessing: {st.session_state['after_clean']}")

        st.markdown("### ⚖️ Distribusi Sentimen")
        dist = df["sentimen"].value_counts()

        st.dataframe(dist)

        fig, ax = plt.subplots()
        ax.bar(dist.index, dist.values,
               color=["#2ecc71", "#e74c3c", "#95a5a6"])
        st.pyplot(fig)

# ==============================
# TRAINING
# ==============================
elif menu == "🤖 Training":

    if "df" not in st.session_state:
        st.warning("Upload data dulu")
    else:
        df = st.session_state["df"]

        if st.button("Mulai Training"):

            X_train, X_test, y_train, y_test = train_test_split(
                df["clean_text"], df["sentimen"],
                test_size=0.2, random_state=42,
                stratify=df["sentimen"]
            )

            col1, col2 = st.columns(2)
            col1.metric("Training", len(X_train))
            col2.metric("Testing", len(X_test))

            st.markdown("### 📄 Contoh Data Training per Kelas")

            df_train = pd.DataFrame({
                "text": X_train,
                "label": y_train
            })

            for kelas in ["positif", "negatif", "netral"]:
                st.write(f"#### {kelas.upper()}")
                contoh = df_train[df_train["label"] == kelas].head(3)
                st.dataframe(contoh)

            st.markdown("### 📄 Contoh Data Testing per Kelas")

            df_test = pd.DataFrame({
                "text": X_test,
                "label": y_test
            })

            for kelas in ["positif", "negatif", "netral"]:
                st.write(f"#### {kelas.upper()}")
                contoh = df_test[df_test["label"] == kelas].head(3)
                st.dataframe(contoh)

            vectorizer = TfidfVectorizer(max_features=3000)
            X_train_vec = vectorizer.fit_transform(X_train)
            X_test_vec = vectorizer.transform(X_test)

            model = MultinomialNB(alpha=0.5, fit_prior=False)
            model.fit(X_train_vec, y_train)

            y_pred = model.predict(X_test_vec)
            acc = accuracy_score(y_test, y_pred)

            st.session_state["model"] = model
            st.session_state["vectorizer"] = vectorizer
            st.session_state["y_test"] = y_test
            st.session_state["y_pred"] = y_pred

            st.success(f"🎯 Akurasi Model: {acc:.4f}")

            col1, col2 = st.columns(2)
            col1.metric("Akurasi", f"{acc*100:.2f}%")
            col2.metric("Jumlah Data Uji", len(y_test))

            st.info("Model dievaluasi menggunakan data testing (20%)")

            st.markdown("### 📊 Top Kata (TF-IDF)")

            feature_names = vectorizer.get_feature_names_out()
            scores = X_train_vec.toarray().sum(axis=0)

            top_idx = scores.argsort()[-10:]
            top_words = [feature_names[i] for i in top_idx]
            top_scores = scores[top_idx]

            fig_feat, ax_feat = plt.subplots()
            ax_feat.barh(top_words, top_scores, color="#3498db")
            st.pyplot(fig_feat)

# ==============================
# EVALUASI
# ==============================
elif menu == "📊 Evaluasi":

    if "model" not in st.session_state:
        st.warning("Training dulu")
    else:
        y_test = st.session_state["y_test"]
        y_pred = st.session_state["y_pred"]

        cm = confusion_matrix(y_test, y_pred)

        fig, ax = plt.subplots(figsize=(6,5))

        sns.heatmap(
            cm,
            annot=True,
            fmt="d",
            cmap="Blues",
            cbar=True,
            linewidths=0.5,
            linecolor='gray',
            xticklabels=["Negatif", "Netral", "Positif"],
            yticklabels=["Negatif", "Netral", "Positif"],
            annot_kws={"size": 10},
            ax=ax
        )

        ax.set_title("📊 Confusion Matrix", fontsize=14, fontweight='bold')
        ax.set_xlabel("Predicted")
        ax.set_ylabel("Actual")

        plt.tight_layout()
        st.pyplot(fig)

        st.dataframe(pd.DataFrame(
            classification_report(y_test, y_pred, output_dict=True)
        ).transpose())